summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWim Taymans <wim.taymans@collabora.co.uk>2011-04-18 10:23:45 +0200
committerWim Taymans <wim.taymans@collabora.co.uk>2011-04-18 10:23:45 +0200
commit7555d0949f231f2263b45b0e791a1884fdc2c771 (patch)
treef4a09aefcf97006a60303e8b93392de6b18788f7
parent8a4ae3dd2de4de1a11d982102e3881e313d4f37a (diff)
parent75d5c41f2903b6703aa4d70b5f9fce6db1ad1e03 (diff)
downloadgstreamer-plugins-good-7555d0949f231f2263b45b0e791a1884fdc2c771.tar.gz
Merge branch 'master' into 0.11
Conflicts: android/apetag.mk android/avi.mk android/flv.mk android/icydemux.mk android/id3demux.mk android/qtdemux.mk android/rtp.mk android/rtpmanager.mk android/rtsp.mk android/soup.mk android/udp.mk android/wavenc.mk android/wavparse.mk configure.ac
-rw-r--r--Android.mk125
-rw-r--r--android/NOTICE504
-rw-r--r--android/apetag.mk49
-rw-r--r--android/avi.mk51
-rw-r--r--android/flv.mk50
-rw-r--r--android/gst/rtpmanager/gstrtpbin-marshal.c321
-rw-r--r--android/gst/rtpmanager/gstrtpbin-marshal.h80
-rw-r--r--android/gst/udp/gstudp-enumtypes.c27
-rw-r--r--android/gst/udp/gstudp-enumtypes.h19
-rw-r--r--android/gst/udp/gstudp-marshal.c117
-rw-r--r--android/gst/udp/gstudp-marshal.h28
-rw-r--r--android/icydemux.mk47
-rw-r--r--android/id3demux.mk50
-rw-r--r--android/qtdemux.mk54
-rw-r--r--android/rtp.mk113
-rw-r--r--android/rtpmanager.mk61
-rw-r--r--android/rtsp.mk53
-rw-r--r--android/soup.mk49
-rw-r--r--android/udp.mk58
-rw-r--r--android/wavenc.mk47
-rw-r--r--android/wavparse.mk47
-rw-r--r--configure.ac11
-rw-r--r--docs/plugins/Makefile.am9
-rw-r--r--docs/plugins/gst-plugins-good-plugins-docs.sgml7
-rw-r--r--docs/plugins/gst-plugins-good-plugins-sections.txt99
-rw-r--r--docs/plugins/gst-plugins-good-plugins.args532
-rw-r--r--docs/plugins/gst-plugins-good-plugins.hierarchy441
-rw-r--r--docs/plugins/gst-plugins-good-plugins.interfaces60
-rw-r--r--docs/plugins/gst-plugins-good-plugins.prerequisites1
-rw-r--r--docs/plugins/inspect/plugin-1394.xml4
-rw-r--r--docs/plugins/inspect/plugin-aasink.xml4
-rw-r--r--docs/plugins/inspect/plugin-alaw.xml4
-rw-r--r--docs/plugins/inspect/plugin-alpha.xml4
-rw-r--r--docs/plugins/inspect/plugin-alphacolor.xml4
-rw-r--r--docs/plugins/inspect/plugin-annodex.xml4
-rw-r--r--docs/plugins/inspect/plugin-apetag.xml4
-rw-r--r--docs/plugins/inspect/plugin-audiofx.xml4
-rw-r--r--docs/plugins/inspect/plugin-audioparsers.xml139
-rw-r--r--docs/plugins/inspect/plugin-auparse.xml4
-rw-r--r--docs/plugins/inspect/plugin-autodetect.xml4
-rw-r--r--docs/plugins/inspect/plugin-avi.xml6
-rw-r--r--docs/plugins/inspect/plugin-cacasink.xml4
-rw-r--r--docs/plugins/inspect/plugin-cairo.xml25
-rw-r--r--docs/plugins/inspect/plugin-cutter.xml4
-rw-r--r--docs/plugins/inspect/plugin-debug.xml4
-rw-r--r--docs/plugins/inspect/plugin-deinterlace.xml4
-rw-r--r--docs/plugins/inspect/plugin-dv.xml4
-rw-r--r--docs/plugins/inspect/plugin-efence.xml4
-rw-r--r--docs/plugins/inspect/plugin-effectv.xml4
-rw-r--r--docs/plugins/inspect/plugin-equalizer.xml4
-rw-r--r--docs/plugins/inspect/plugin-esdsink.xml4
-rw-r--r--docs/plugins/inspect/plugin-flac.xml4
-rw-r--r--docs/plugins/inspect/plugin-flv.xml8
-rw-r--r--docs/plugins/inspect/plugin-flxdec.xml4
-rw-r--r--docs/plugins/inspect/plugin-gconfelements.xml4
-rw-r--r--docs/plugins/inspect/plugin-gdkpixbuf.xml4
-rw-r--r--docs/plugins/inspect/plugin-goom.xml4
-rw-r--r--docs/plugins/inspect/plugin-goom2k1.xml4
-rw-r--r--docs/plugins/inspect/plugin-gstrtpmanager.xml4
-rw-r--r--docs/plugins/inspect/plugin-halelements.xml4
-rw-r--r--docs/plugins/inspect/plugin-icydemux.xml4
-rw-r--r--docs/plugins/inspect/plugin-id3demux.xml4
-rw-r--r--docs/plugins/inspect/plugin-imagefreeze.xml4
-rw-r--r--docs/plugins/inspect/plugin-interleave.xml4
-rw-r--r--docs/plugins/inspect/plugin-jack.xml4
-rw-r--r--docs/plugins/inspect/plugin-jpeg.xml4
-rw-r--r--docs/plugins/inspect/plugin-level.xml4
-rw-r--r--docs/plugins/inspect/plugin-matroska.xml6
-rw-r--r--docs/plugins/inspect/plugin-monoscope.xml4
-rw-r--r--docs/plugins/inspect/plugin-mulaw.xml4
-rw-r--r--docs/plugins/inspect/plugin-multifile.xml4
-rw-r--r--docs/plugins/inspect/plugin-multipart.xml4
-rw-r--r--docs/plugins/inspect/plugin-navigationtest.xml4
-rw-r--r--docs/plugins/inspect/plugin-oss4.xml4
-rw-r--r--docs/plugins/inspect/plugin-ossaudio.xml4
-rw-r--r--docs/plugins/inspect/plugin-png.xml6
-rw-r--r--docs/plugins/inspect/plugin-pulseaudio.xml4
-rw-r--r--docs/plugins/inspect/plugin-quicktime.xml150
-rw-r--r--docs/plugins/inspect/plugin-replaygain.xml4
-rw-r--r--docs/plugins/inspect/plugin-rtp.xml4
-rw-r--r--docs/plugins/inspect/plugin-rtsp.xml4
-rw-r--r--docs/plugins/inspect/plugin-shapewipe.xml4
-rw-r--r--docs/plugins/inspect/plugin-shout2send.xml2
-rw-r--r--docs/plugins/inspect/plugin-smpte.xml4
-rw-r--r--docs/plugins/inspect/plugin-soup.xml4
-rw-r--r--docs/plugins/inspect/plugin-spectrum.xml4
-rw-r--r--docs/plugins/inspect/plugin-speex.xml4
-rw-r--r--docs/plugins/inspect/plugin-udp.xml4
-rw-r--r--docs/plugins/inspect/plugin-video4linux2.xml37
-rw-r--r--docs/plugins/inspect/plugin-videobox.xml4
-rw-r--r--docs/plugins/inspect/plugin-videocrop.xml4
-rw-r--r--docs/plugins/inspect/plugin-videofilter.xml8
-rw-r--r--docs/plugins/inspect/plugin-videomixer.xml4
-rw-r--r--docs/plugins/inspect/plugin-wavenc.xml4
-rw-r--r--docs/plugins/inspect/plugin-wavpack.xml4
-rw-r--r--docs/plugins/inspect/plugin-wavparse.xml4
-rw-r--r--docs/plugins/inspect/plugin-ximagesrc.xml4
-rw-r--r--docs/plugins/inspect/plugin-y4menc.xml4
-rw-r--r--ext/flac/gstflacenc.c7
-rw-r--r--ext/jack/gstjackaudiosink.c38
-rw-r--r--ext/jack/gstjackaudiosrc.c37
-rw-r--r--ext/jpeg/gstjpegdec.c4
-rw-r--r--ext/jpeg/gstjpegenc.c3
-rw-r--r--ext/pulse/pulsesink.c32
-rw-r--r--ext/pulse/pulsesrc.c4
-rw-r--r--ext/raw1394/gstdv1394src.c2
-rw-r--r--ext/raw1394/gsthdv1394src.c2
-rw-r--r--ext/speex/gstspeexenc.c14
-rw-r--r--gst-plugins-good.spec.in1
-rw-r--r--gst/alpha/Makefile.am14
-rw-r--r--gst/apetag/Makefile.am14
-rw-r--r--gst/audiofx/Makefile.am13
-rw-r--r--gst/audiofx/audiowsincband.c85
-rw-r--r--gst/audiofx/audiowsinclimit.c52
-rw-r--r--gst/audioparsers/Makefile.am18
-rw-r--r--gst/audioparsers/gstaacparse.c717
-rw-r--r--gst/audioparsers/gstaacparse.h109
-rw-r--r--gst/audioparsers/gstac3parse.c507
-rw-r--r--gst/audioparsers/gstac3parse.h73
-rw-r--r--gst/audioparsers/gstamrparse.c378
-rw-r--r--gst/audioparsers/gstamrparse.h82
-rw-r--r--gst/audioparsers/gstdcaparse.c451
-rw-r--r--gst/audioparsers/gstdcaparse.h78
-rw-r--r--gst/audioparsers/gstflacparse.c1355
-rw-r--r--gst/audioparsers/gstflacparse.h92
-rw-r--r--gst/audioparsers/gstmpegaudioparse.c1265
-rw-r--r--gst/audioparsers/gstmpegaudioparse.h111
-rw-r--r--gst/audioparsers/plugin.c57
-rw-r--r--gst/auparse/Makefile.am14
-rw-r--r--gst/autodetect/Makefile.am14
-rw-r--r--gst/avi/Makefile.am14
-rw-r--r--gst/avi/gstavidemux.c4
-rw-r--r--gst/cutter/Makefile.am14
-rw-r--r--gst/debugutils/Makefile.am13
-rw-r--r--gst/debugutils/gstcapsdebug.c55
-rw-r--r--gst/deinterlace/Makefile.am14
-rw-r--r--gst/deinterlace/tvtime-dist.c110
-rw-r--r--gst/deinterlace/tvtime-dist.h18
-rw-r--r--gst/deinterlace/tvtime/greedyh.c2
-rw-r--r--gst/effectv/Makefile.am14
-rw-r--r--gst/effectv/gstedge.c3
-rw-r--r--gst/equalizer/Makefile.am13
-rw-r--r--gst/flv/Makefile.am14
-rw-r--r--gst/flv/gstflvdemux.c35
-rw-r--r--gst/flv/gstflvdemux.h1
-rw-r--r--gst/flx/Makefile.am14
-rw-r--r--gst/goom/Makefile.am13
-rw-r--r--gst/goom2k1/Makefile.am14
-rw-r--r--gst/icydemux/Makefile.am14
-rw-r--r--gst/id3demux/Makefile.am14
-rw-r--r--gst/imagefreeze/Makefile.am13
-rw-r--r--gst/imagefreeze/gstimagefreeze.c6
-rw-r--r--gst/interleave/Makefile.am14
-rw-r--r--gst/law/Makefile.am25
-rw-r--r--gst/level/Makefile.am14
-rw-r--r--gst/matroska/Makefile.am15
-rw-r--r--gst/matroska/matroska-demux.c54
-rw-r--r--gst/matroska/matroska-mux.c2
-rw-r--r--gst/matroska/matroska-parse.c12
-rw-r--r--gst/monoscope/Makefile.am13
-rw-r--r--gst/multifile/Makefile.am14
-rw-r--r--gst/multipart/Makefile.am14
-rw-r--r--gst/qtdemux/Makefile.am26
-rw-r--r--gst/quicktime/LEGAL (renamed from gst/qtdemux/LEGAL)0
-rw-r--r--gst/quicktime/Makefile.am51
-rw-r--r--gst/quicktime/atoms.c4423
-rw-r--r--gst/quicktime/atoms.h956
-rw-r--r--gst/quicktime/atomsrecovery.c1095
-rw-r--r--gst/quicktime/atomsrecovery.h159
-rw-r--r--gst/quicktime/descriptors.c457
-rw-r--r--gst/quicktime/descriptors.h151
-rw-r--r--gst/quicktime/fourcc.h243
-rw-r--r--gst/quicktime/ftypcc.h68
-rw-r--r--gst/quicktime/gstqtmoovrecover.c389
-rw-r--r--gst/quicktime/gstqtmoovrecover.h88
-rw-r--r--gst/quicktime/gstqtmux.c3525
-rw-r--r--gst/quicktime/gstqtmux.h228
-rw-r--r--gst/quicktime/gstqtmuxmap.c370
-rw-r--r--gst/quicktime/gstqtmuxmap.h83
-rw-r--r--gst/quicktime/gstrtpxqtdepay.c (renamed from gst/qtdemux/gstrtpxqtdepay.c)15
-rw-r--r--gst/quicktime/gstrtpxqtdepay.h (renamed from gst/qtdemux/gstrtpxqtdepay.h)0
-rw-r--r--gst/quicktime/properties.c210
-rw-r--r--gst/quicktime/properties.h87
-rw-r--r--gst/quicktime/qtatomparser.h (renamed from gst/qtdemux/qtatomparser.h)0
-rw-r--r--gst/quicktime/qtdemux.c (renamed from gst/qtdemux/qtdemux.c)14
-rw-r--r--gst/quicktime/qtdemux.h (renamed from gst/qtdemux/qtdemux.h)0
-rw-r--r--gst/quicktime/qtdemux.vcproj (renamed from gst/qtdemux/qtdemux.vcproj)0
-rw-r--r--gst/quicktime/qtdemux_dump.c (renamed from gst/qtdemux/qtdemux_dump.c)0
-rw-r--r--gst/quicktime/qtdemux_dump.h (renamed from gst/qtdemux/qtdemux_dump.h)0
-rw-r--r--gst/quicktime/qtdemux_fourcc.h (renamed from gst/qtdemux/qtdemux_fourcc.h)0
-rw-r--r--gst/quicktime/qtdemux_lang.c (renamed from gst/qtdemux/qtdemux_lang.c)0
-rw-r--r--gst/quicktime/qtdemux_lang.h (renamed from gst/qtdemux/qtdemux_lang.h)0
-rw-r--r--gst/quicktime/qtdemux_types.c (renamed from gst/qtdemux/qtdemux_types.c)0
-rw-r--r--gst/quicktime/qtdemux_types.h (renamed from gst/qtdemux/qtdemux_types.h)0
-rw-r--r--gst/quicktime/qtpalette.h (renamed from gst/qtdemux/qtpalette.h)0
-rw-r--r--gst/quicktime/quicktime.c (renamed from gst/qtdemux/quicktime.c)7
-rw-r--r--gst/replaygain/Makefile.am15
-rw-r--r--gst/rtp/Makefile.am14
-rw-r--r--gst/rtp/gstrtpamrdepay.c3
-rw-r--r--gst/rtp/gstrtpbvdepay.c2
-rw-r--r--gst/rtp/gstrtpbvpay.c2
-rw-r--r--gst/rtp/gstrtpg722pay.c4
-rw-r--r--gst/rtp/gstrtpgsmpay.c10
-rw-r--r--gst/rtp/gstrtpgstdepay.c6
-rw-r--r--gst/rtp/gstrtpgstpay.c18
-rw-r--r--gst/rtp/gstrtpj2kpay.c2
-rw-r--r--gst/rtp/gstrtpmp4gpay.c4
-rw-r--r--gst/rtp/gstrtpmp4vpay.c4
-rw-r--r--gst/rtp/gstrtpmpadepay.c5
-rw-r--r--gst/rtp/gstrtpqcelpdepay.c9
-rw-r--r--gst/rtp/gstrtpspeexpay.c5
-rw-r--r--gst/rtpmanager/Makefile.am14
-rw-r--r--gst/rtpmanager/gstrtpbin-marshal.list2
-rw-r--r--gst/rtpmanager/gstrtpjitterbuffer.c12
-rw-r--r--gst/rtpmanager/gstrtpptdemux.c4
-rw-r--r--gst/rtpmanager/gstrtpsession.c59
-rw-r--r--gst/rtpmanager/gstrtpssrcdemux.c12
-rw-r--r--gst/rtpmanager/rtpsession.c112
-rw-r--r--gst/rtsp/Makefile.am14
-rw-r--r--gst/shapewipe/Makefile.am14
-rw-r--r--gst/shapewipe/gstshapewipe.c3
-rw-r--r--gst/smpte/Makefile.am13
-rw-r--r--gst/spectrum/Makefile.am15
-rw-r--r--gst/udp/Makefile.am14
-rw-r--r--gst/videobox/Makefile.am15
-rw-r--r--gst/videobox/gstvideoboxorc-dist.c27
-rw-r--r--gst/videobox/gstvideoboxorc-dist.h12
-rw-r--r--gst/videocrop/Makefile.am15
-rw-r--r--gst/videofilter/Makefile.am15
-rw-r--r--gst/videofilter/gstvideobalance.c19
-rw-r--r--gst/videofilter/gstvideoflip.c4
-rw-r--r--gst/videomixer/Makefile.am15
-rw-r--r--gst/videomixer/blend.c10
-rw-r--r--gst/videomixer/blendorc-dist.c813
-rw-r--r--gst/videomixer/blendorc-dist.h23
-rw-r--r--gst/videomixer/blendorc.orc6
-rw-r--r--gst/videomixer/gstcollectpads2.c5
-rw-r--r--gst/videomixer/videomixer2.c7
-rw-r--r--gst/wavenc/Makefile.am14
-rw-r--r--gst/wavparse/Makefile.am14
-rw-r--r--gst/y4m/Makefile.am14
-rw-r--r--gst/y4m/gsty4mencode.c4
-rw-r--r--po/POTFILES.in2
-rw-r--r--po/bg.po21
-rw-r--r--po/cs.po22
-rw-r--r--po/de.po22
-rw-r--r--po/es.po20
-rw-r--r--po/id.po34
-rw-r--r--po/sl.po219
-rw-r--r--sys/directsound/gstdirectsoundsink.c8
-rw-r--r--sys/oss4/oss4-mixer-slider.c2
-rw-r--r--sys/oss4/oss4-mixer-switch.c3
-rw-r--r--sys/oss4/oss4-property-probe.c2
-rw-r--r--sys/oss4/oss4-source.c8
-rw-r--r--sys/v4l2/gstv4l2radio.c2
-rw-r--r--sys/v4l2/gstv4l2sink.c2
-rw-r--r--sys/v4l2/gstv4l2src.c2
-rw-r--r--tests/check/Makefile.am30
-rw-r--r--tests/check/elements/.gitignore6
-rw-r--r--tests/check/elements/aacparse.c240
-rw-r--r--tests/check/elements/ac3parse.c163
-rw-r--r--tests/check/elements/amrparse.c327
-rw-r--r--tests/check/elements/deinterlace.c2
-rw-r--r--tests/check/elements/flacparse.c299
-rw-r--r--tests/check/elements/mpegaudioparse.c172
-rw-r--r--tests/check/elements/parser.c434
-rw-r--r--tests/check/elements/parser.h95
-rw-r--r--tests/check/elements/qtmux.c590
-rw-r--r--tests/check/elements/rtp-payloading.c3
-rw-r--r--tests/check/pipelines/.gitignore1
-rw-r--r--tests/check/pipelines/flacdec.c6
-rw-r--r--tests/check/pipelines/tagschecking.c350
-rw-r--r--tests/examples/cairo/cairo_overlay.c2
-rw-r--r--tests/examples/level/level-example.c13
-rw-r--r--tests/examples/rtp/server-alsasrc-PCMA.c26
-rw-r--r--tests/icles/videocrop-test.c3
-rw-r--r--tests/icles/ximagesrc-test.c3
-rw-r--r--win32/common/config.h16
-rw-r--r--win32/common/gstrtpbin-marshal.c74
-rw-r--r--win32/common/gstrtpbin-marshal.h19
280 files changed, 23888 insertions, 3388 deletions
diff --git a/Android.mk b/Android.mk
index 146d61293..ec380920b 100644
--- a/Android.mk
+++ b/Android.mk
@@ -1,20 +1,113 @@
LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
-GSTREAMER_TOP := $(LOCAL_PATH)
+GST_PLUGINS_GOOD_TOP := $(LOCAL_PATH)
-include $(CLEAR_VARS)
+GST_PLUGINS_GOOD_BUILT_SOURCES = \
+ gst/alpha/Android.mk \
+ gst/apetag/Android.mk \
+ gst/audiofx/Android.mk \
+ gst/auparse/Android.mk \
+ gst/autodetect/Android.mk \
+ gst/avi/Android.mk \
+ gst/cutter/Android.mk \
+ gst/debugutils/Android.mk \
+ gst/deinterlace/Android.mk \
+ gst/effectv/Android.mk \
+ gst/equalizer/Android.mk \
+ gst/flv/Android.mk \
+ gst/flx/Android.mk \
+ gst/goom/Android.mk \
+ gst/goom2k1/Android.mk \
+ gst/icydemux/Android.mk \
+ gst/id3demux/Android.mk \
+ gst/imagefreeze/Android.mk \
+ gst/interleave/Android.mk \
+ gst/law/Android.mk \
+ gst/level/Android.mk \
+ gst/matroska/Android.mk \
+ gst/multifile/Android.mk \
+ gst/multipart/Android.mk \
+ gst/quicktime/Android.mk \
+ gst/replaygain/Android.mk \
+ gst/rtp/Android.mk \
+ gst/rtpmanager/Android.mk \
+ gst/rtsp/Android.mk \
+ gst/shapewipe/Android.mk \
+ gst/smpte/Android.mk \
+ gst/spectrum/Android.mk \
+ gst/udp/Android.mk \
+ gst/videobox/Android.mk \
+ gst/videocrop/Android.mk \
+ gst/videofilter/Android.mk \
+ gst/videomixer/Android.mk \
+ gst/wavenc/Android.mk \
+ gst/monoscope/Android.mk \
+ gst/y4m/Android.mk \
+ gst/wavparse/Android.mk
+
+GST_PLUGINS_GOOD_BUILT_SOURCES := $(patsubst %, $(abspath $(GST_PLUGINS_GOOD_TOP))/%, $(GST_PLUGINS_GOOD_BUILT_SOURCES))
+
+.PHONY: gst-plugins-good-configure gst-plugins-good-configure-real
+gst-plugins-good-configure-real:
+ cd $(GST_PLUGINS_GOOD_TOP) ; \
+ CC="$(CONFIGURE_CC)" \
+ CFLAGS="$(CONFIGURE_CFLAGS)" \
+ LD=$(TARGET_LD) \
+ LDFLAGS="$(CONFIGURE_LDFLAGS)" \
+ CPP=$(CONFIGURE_CPP) \
+ CPPFLAGS="$(CONFIGURE_CPPFLAGS)" \
+ PKG_CONFIG_LIBDIR="$(CONFIGURE_PKG_CONFIG_LIBDIR)" \
+ PKG_CONFIG_TOP_BUILD_DIR=/ \
+ $(abspath $(GST_PLUGINS_GOOD_TOP))/$(CONFIGURE) --host=arm-linux-androideabi \
+ --prefix=/system --disable-orc --disable-valgrind --disable-gtk-doc && \
+ for file in $(GST_PLUGINS_GOOD_BUILT_SOURCES); do \
+ rm -f $$file && \
+ make -C $$(dirname $$file) $$(basename $$file) ; \
+ done
+
+gst-plugins-good-configure: gst-plugins-good-configure-real
+
+CONFIGURE_TARGETS += gst-plugins-good-configure
-#plugins
-include $(GSTREAMER_TOP)/android/qtdemux.mk
-include $(GSTREAMER_TOP)/android/avi.mk
-include $(GSTREAMER_TOP)/android/wavparse.mk
-include $(GSTREAMER_TOP)/android/rtp.mk
-include $(GSTREAMER_TOP)/android/rtsp.mk
-include $(GSTREAMER_TOP)/android/id3demux.mk
-include $(GSTREAMER_TOP)/android/udp.mk
-include $(GSTREAMER_TOP)/android/flv.mk
-include $(GSTREAMER_TOP)/android/soup.mk
-include $(GSTREAMER_TOP)/android/rtpmanager.mk
-include $(GSTREAMER_TOP)/android/icydemux.mk
-include $(GSTREAMER_TOP)/android/wavenc.mk
-include $(GSTREAMER_TOP)/android/apetag.mk
+-include $(GST_PLUGINS_GOOD_TOP)/gst/alpha/Android.mk
+-include $(GST_PLUGINS_GOOD_TOP)/gst/apetag/Android.mk
+-include $(GST_PLUGINS_GOOD_TOP)/gst/audiofx/Android.mk
+-include $(GST_PLUGINS_GOOD_TOP)/gst/auparse/Android.mk
+-include $(GST_PLUGINS_GOOD_TOP)/gst/autodetect/Android.mk
+-include $(GST_PLUGINS_GOOD_TOP)/gst/avi/Android.mk
+-include $(GST_PLUGINS_GOOD_TOP)/gst/cutter/Android.mk
+-include $(GST_PLUGINS_GOOD_TOP)/gst/debugutils/Android.mk
+-include $(GST_PLUGINS_GOOD_TOP)/gst/deinterlace/Android.mk
+-include $(GST_PLUGINS_GOOD_TOP)/gst/effectv/Android.mk
+-include $(GST_PLUGINS_GOOD_TOP)/gst/equalizer/Android.mk
+-include $(GST_PLUGINS_GOOD_TOP)/gst/flv/Android.mk
+-include $(GST_PLUGINS_GOOD_TOP)/gst/flx/Android.mk
+-include $(GST_PLUGINS_GOOD_TOP)/gst/goom/Android.mk
+-include $(GST_PLUGINS_GOOD_TOP)/gst/goom2k1/Android.mk
+-include $(GST_PLUGINS_GOOD_TOP)/gst/icydemux/Android.mk
+-include $(GST_PLUGINS_GOOD_TOP)/gst/id3demux/Android.mk
+-include $(GST_PLUGINS_GOOD_TOP)/gst/imagefreeze/Android.mk
+-include $(GST_PLUGINS_GOOD_TOP)/gst/interleave/Android.mk
+-include $(GST_PLUGINS_GOOD_TOP)/gst/law/Android.mk
+-include $(GST_PLUGINS_GOOD_TOP)/gst/level/Android.mk
+-include $(GST_PLUGINS_GOOD_TOP)/gst/matroska/Android.mk
+-include $(GST_PLUGINS_GOOD_TOP)/gst/multifile/Android.mk
+-include $(GST_PLUGINS_GOOD_TOP)/gst/multipart/Android.mk
+-include $(GST_PLUGINS_GOOD_TOP)/gst/quicktime/Android.mk
+-include $(GST_PLUGINS_GOOD_TOP)/gst/replaygain/Android.mk
+-include $(GST_PLUGINS_GOOD_TOP)/gst/rtp/Android.mk
+-include $(GST_PLUGINS_GOOD_TOP)/gst/rtpmanager/Android.mk
+-include $(GST_PLUGINS_GOOD_TOP)/gst/rtsp/Android.mk
+-include $(GST_PLUGINS_GOOD_TOP)/gst/shapewipe/Android.mk
+-include $(GST_PLUGINS_GOOD_TOP)/gst/smpte/Android.mk
+-include $(GST_PLUGINS_GOOD_TOP)/gst/spectrum/Android.mk
+-include $(GST_PLUGINS_GOOD_TOP)/gst/udp/Android.mk
+-include $(GST_PLUGINS_GOOD_TOP)/gst/videobox/Android.mk
+-include $(GST_PLUGINS_GOOD_TOP)/gst/videocrop/Android.mk
+-include $(GST_PLUGINS_GOOD_TOP)/gst/videofilter/Android.mk
+-include $(GST_PLUGINS_GOOD_TOP)/gst/videomixer/Android.mk
+-include $(GST_PLUGINS_GOOD_TOP)/gst/wavenc/Android.mk
+-include $(GST_PLUGINS_GOOD_TOP)/gst/wavparse/Android.mk
+-include $(GST_PLUGINS_GOOD_TOP)/gst/y4m/Android.mk
+-include $(GST_PLUGINS_GOOD_TOP)/gst/monoscope/Android.mk
diff --git a/android/NOTICE b/android/NOTICE
deleted file mode 100644
index 8add30ad5..000000000
--- a/android/NOTICE
+++ /dev/null
@@ -1,504 +0,0 @@
- GNU LESSER GENERAL PUBLIC LICENSE
- Version 2.1, February 1999
-
- Copyright (C) 1991, 1999 Free Software Foundation, Inc.
- 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-[This is the first released version of the Lesser GPL. It also counts
- as the successor of the GNU Library Public License, version 2, hence
- the version number 2.1.]
-
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-Licenses are intended to guarantee your freedom to share and change
-free software--to make sure the software is free for all its users.
-
- This license, the Lesser General Public License, applies to some
-specially designated software packages--typically libraries--of the
-Free Software Foundation and other authors who decide to use it. You
-can use it too, but we suggest you first think carefully about whether
-this license or the ordinary General Public License is the better
-strategy to use in any particular case, based on the explanations below.
-
- When we speak of free software, we are referring to freedom of use,
-not price. Our General Public Licenses are designed to make sure that
-you have the freedom to distribute copies of free software (and charge
-for this service if you wish); that you receive source code or can get
-it if you want it; that you can change the software and use pieces of
-it in new free programs; and that you are informed that you can do
-these things.
-
- To protect your rights, we need to make restrictions that forbid
-distributors to deny you these rights or to ask you to surrender these
-rights. These restrictions translate to certain responsibilities for
-you if you distribute copies of the library or if you modify it.
-
- For example, if you distribute copies of the library, whether gratis
-or for a fee, you must give the recipients all the rights that we gave
-you. You must make sure that they, too, receive or can get the source
-code. If you link other code with the library, you must provide
-complete object files to the recipients, so that they can relink them
-with the library after making changes to the library and recompiling
-it. And you must show them these terms so they know their rights.
-
- We protect your rights with a two-step method: (1) we copyright the
-library, and (2) we offer you this license, which gives you legal
-permission to copy, distribute and/or modify the library.
-
- To protect each distributor, we want to make it very clear that
-there is no warranty for the free library. Also, if the library is
-modified by someone else and passed on, the recipients should know
-that what they have is not the original version, so that the original
-author's reputation will not be affected by problems that might be
-introduced by others.
-
- Finally, software patents pose a constant threat to the existence of
-any free program. We wish to make sure that a company cannot
-effectively restrict the users of a free program by obtaining a
-restrictive license from a patent holder. Therefore, we insist that
-any patent license obtained for a version of the library must be
-consistent with the full freedom of use specified in this license.
-
- Most GNU software, including some libraries, is covered by the
-ordinary GNU General Public License. This license, the GNU Lesser
-General Public License, applies to certain designated libraries, and
-is quite different from the ordinary General Public License. We use
-this license for certain libraries in order to permit linking those
-libraries into non-free programs.
-
- When a program is linked with a library, whether statically or using
-a shared library, the combination of the two is legally speaking a
-combined work, a derivative of the original library. The ordinary
-General Public License therefore permits such linking only if the
-entire combination fits its criteria of freedom. The Lesser General
-Public License permits more lax criteria for linking other code with
-the library.
-
- We call this license the "Lesser" General Public License because it
-does Less to protect the user's freedom than the ordinary General
-Public License. It also provides other free software developers Less
-of an advantage over competing non-free programs. These disadvantages
-are the reason we use the ordinary General Public License for many
-libraries. However, the Lesser license provides advantages in certain
-special circumstances.
-
- For example, on rare occasions, there may be a special need to
-encourage the widest possible use of a certain library, so that it becomes
-a de-facto standard. To achieve this, non-free programs must be
-allowed to use the library. A more frequent case is that a free
-library does the same job as widely used non-free libraries. In this
-case, there is little to gain by limiting the free library to free
-software only, so we use the Lesser General Public License.
-
- In other cases, permission to use a particular library in non-free
-programs enables a greater number of people to use a large body of
-free software. For example, permission to use the GNU C Library in
-non-free programs enables many more people to use the whole GNU
-operating system, as well as its variant, the GNU/Linux operating
-system.
-
- Although the Lesser General Public License is Less protective of the
-users' freedom, it does ensure that the user of a program that is
-linked with the Library has the freedom and the wherewithal to run
-that program using a modified version of the Library.
-
- The precise terms and conditions for copying, distribution and
-modification follow. Pay close attention to the difference between a
-"work based on the library" and a "work that uses the library". The
-former contains code derived from the library, whereas the latter must
-be combined with the library in order to run.
-
- GNU LESSER GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License Agreement applies to any software library or other
-program which contains a notice placed by the copyright holder or
-other authorized party saying it may be distributed under the terms of
-this Lesser General Public License (also called "this License").
-Each licensee is addressed as "you".
-
- A "library" means a collection of software functions and/or data
-prepared so as to be conveniently linked with application programs
-(which use some of those functions and data) to form executables.
-
- The "Library", below, refers to any such software library or work
-which has been distributed under these terms. A "work based on the
-Library" means either the Library or any derivative work under
-copyright law: that is to say, a work containing the Library or a
-portion of it, either verbatim or with modifications and/or translated
-straightforwardly into another language. (Hereinafter, translation is
-included without limitation in the term "modification".)
-
- "Source code" for a work means the preferred form of the work for
-making modifications to it. For a library, complete source code means
-all the source code for all modules it contains, plus any associated
-interface definition files, plus the scripts used to control compilation
-and installation of the library.
-
- Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running a program using the Library is not restricted, and output from
-such a program is covered only if its contents constitute a work based
-on the Library (independent of the use of the Library in a tool for
-writing it). Whether that is true depends on what the Library does
-and what the program that uses the Library does.
-
- 1. You may copy and distribute verbatim copies of the Library's
-complete source code as you receive it, in any medium, provided that
-you conspicuously and appropriately publish on each copy an
-appropriate copyright notice and disclaimer of warranty; keep intact
-all the notices that refer to this License and to the absence of any
-warranty; and distribute a copy of this License along with the
-Library.
-
- You may charge a fee for the physical act of transferring a copy,
-and you may at your option offer warranty protection in exchange for a
-fee.
-
- 2. You may modify your copy or copies of the Library or any portion
-of it, thus forming a work based on the Library, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) The modified work must itself be a software library.
-
- b) You must cause the files modified to carry prominent notices
- stating that you changed the files and the date of any change.
-
- c) You must cause the whole of the work to be licensed at no
- charge to all third parties under the terms of this License.
-
- d) If a facility in the modified Library refers to a function or a
- table of data to be supplied by an application program that uses
- the facility, other than as an argument passed when the facility
- is invoked, then you must make a good faith effort to ensure that,
- in the event an application does not supply such function or
- table, the facility still operates, and performs whatever part of
- its purpose remains meaningful.
-
- (For example, a function in a library to compute square roots has
- a purpose that is entirely well-defined independent of the
- application. Therefore, Subsection 2d requires that any
- application-supplied function or table used by this function must
- be optional: if the application does not supply it, the square
- root function must still compute square roots.)
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Library,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Library, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote
-it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Library.
-
-In addition, mere aggregation of another work not based on the Library
-with the Library (or with a work based on the Library) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may opt to apply the terms of the ordinary GNU General Public
-License instead of this License to a given copy of the Library. To do
-this, you must alter all the notices that refer to this License, so
-that they refer to the ordinary GNU General Public License, version 2,
-instead of to this License. (If a newer version than version 2 of the
-ordinary GNU General Public License has appeared, then you can specify
-that version instead if you wish.) Do not make any other change in
-these notices.
-
- Once this change is made in a given copy, it is irreversible for
-that copy, so the ordinary GNU General Public License applies to all
-subsequent copies and derivative works made from that copy.
-
- This option is useful when you wish to copy part of the code of
-the Library into a program that is not a library.
-
- 4. You may copy and distribute the Library (or a portion or
-derivative of it, under Section 2) in object code or executable form
-under the terms of Sections 1 and 2 above provided that you accompany
-it with the complete corresponding machine-readable source code, which
-must be distributed under the terms of Sections 1 and 2 above on a
-medium customarily used for software interchange.
-
- If distribution of object code is made by offering access to copy
-from a designated place, then offering equivalent access to copy the
-source code from the same place satisfies the requirement to
-distribute the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
- 5. A program that contains no derivative of any portion of the
-Library, but is designed to work with the Library by being compiled or
-linked with it, is called a "work that uses the Library". Such a
-work, in isolation, is not a derivative work of the Library, and
-therefore falls outside the scope of this License.
-
- However, linking a "work that uses the Library" with the Library
-creates an executable that is a derivative of the Library (because it
-contains portions of the Library), rather than a "work that uses the
-library". The executable is therefore covered by this License.
-Section 6 states terms for distribution of such executables.
-
- When a "work that uses the Library" uses material from a header file
-that is part of the Library, the object code for the work may be a
-derivative work of the Library even though the source code is not.
-Whether this is true is especially significant if the work can be
-linked without the Library, or if the work is itself a library. The
-threshold for this to be true is not precisely defined by law.
-
- If such an object file uses only numerical parameters, data
-structure layouts and accessors, and small macros and small inline
-functions (ten lines or less in length), then the use of the object
-file is unrestricted, regardless of whether it is legally a derivative
-work. (Executables containing this object code plus portions of the
-Library will still fall under Section 6.)
-
- Otherwise, if the work is a derivative of the Library, you may
-distribute the object code for the work under the terms of Section 6.
-Any executables containing that work also fall under Section 6,
-whether or not they are linked directly with the Library itself.
-
- 6. As an exception to the Sections above, you may also combine or
-link a "work that uses the Library" with the Library to produce a
-work containing portions of the Library, and distribute that work
-under terms of your choice, provided that the terms permit
-modification of the work for the customer's own use and reverse
-engineering for debugging such modifications.
-
- You must give prominent notice with each copy of the work that the
-Library is used in it and that the Library and its use are covered by
-this License. You must supply a copy of this License. If the work
-during execution displays copyright notices, you must include the
-copyright notice for the Library among them, as well as a reference
-directing the user to the copy of this License. Also, you must do one
-of these things:
-
- a) Accompany the work with the complete corresponding
- machine-readable source code for the Library including whatever
- changes were used in the work (which must be distributed under
- Sections 1 and 2 above); and, if the work is an executable linked
- with the Library, with the complete machine-readable "work that
- uses the Library", as object code and/or source code, so that the
- user can modify the Library and then relink to produce a modified
- executable containing the modified Library. (It is understood
- that the user who changes the contents of definitions files in the
- Library will not necessarily be able to recompile the application
- to use the modified definitions.)
-
- b) Use a suitable shared library mechanism for linking with the
- Library. A suitable mechanism is one that (1) uses at run time a
- copy of the library already present on the user's computer system,
- rather than copying library functions into the executable, and (2)
- will operate properly with a modified version of the library, if
- the user installs one, as long as the modified version is
- interface-compatible with the version that the work was made with.
-
- c) Accompany the work with a written offer, valid for at
- least three years, to give the same user the materials
- specified in Subsection 6a, above, for a charge no more
- than the cost of performing this distribution.
-
- d) If distribution of the work is made by offering access to copy
- from a designated place, offer equivalent access to copy the above
- specified materials from the same place.
-
- e) Verify that the user has already received a copy of these
- materials or that you have already sent this user a copy.
-
- For an executable, the required form of the "work that uses the
-Library" must include any data and utility programs needed for
-reproducing the executable from it. However, as a special exception,
-the materials to be distributed need not include anything that is
-normally distributed (in either source or binary form) with the major
-components (compiler, kernel, and so on) of the operating system on
-which the executable runs, unless that component itself accompanies
-the executable.
-
- It may happen that this requirement contradicts the license
-restrictions of other proprietary libraries that do not normally
-accompany the operating system. Such a contradiction means you cannot
-use both them and the Library together in an executable that you
-distribute.
-
- 7. You may place library facilities that are a work based on the
-Library side-by-side in a single library together with other library
-facilities not covered by this License, and distribute such a combined
-library, provided that the separate distribution of the work based on
-the Library and of the other library facilities is otherwise
-permitted, and provided that you do these two things:
-
- a) Accompany the combined library with a copy of the same work
- based on the Library, uncombined with any other library
- facilities. This must be distributed under the terms of the
- Sections above.
-
- b) Give prominent notice with the combined library of the fact
- that part of it is a work based on the Library, and explaining
- where to find the accompanying uncombined form of the same work.
-
- 8. You may not copy, modify, sublicense, link with, or distribute
-the Library except as expressly provided under this License. Any
-attempt otherwise to copy, modify, sublicense, link with, or
-distribute the Library is void, and will automatically terminate your
-rights under this License. However, parties who have received copies,
-or rights, from you under this License will not have their licenses
-terminated so long as such parties remain in full compliance.
-
- 9. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Library or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Library (or any work based on the
-Library), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Library or works based on it.
-
- 10. Each time you redistribute the Library (or any work based on the
-Library), the recipient automatically receives a license from the
-original licensor to copy, distribute, link with or modify the Library
-subject to these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties with
-this License.
-
- 11. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Library at all. For example, if a patent
-license would not permit royalty-free redistribution of the Library by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Library.
-
-If any portion of this section is held invalid or unenforceable under any
-particular circumstance, the balance of the section is intended to apply,
-and the section as a whole is intended to apply in other circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
- 12. If the distribution and/or use of the Library is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Library under this License may add
-an explicit geographical distribution limitation excluding those countries,
-so that distribution is permitted only in or among countries not thus
-excluded. In such case, this License incorporates the limitation as if
-written in the body of this License.
-
- 13. The Free Software Foundation may publish revised and/or new
-versions of the Lesser General Public License from time to time.
-Such new versions will be similar in spirit to the present version,
-but may differ in detail to address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Library
-specifies a version number of this License which applies to it and
-"any later version", you have the option of following the terms and
-conditions either of that version or of any later version published by
-the Free Software Foundation. If the Library does not specify a
-license version number, you may choose any version ever published by
-the Free Software Foundation.
-
- 14. If you wish to incorporate parts of the Library into other free
-programs whose distribution conditions are incompatible with these,
-write to the author to ask for permission. For software which is
-copyrighted by the Free Software Foundation, write to the Free
-Software Foundation; we sometimes make exceptions for this. Our
-decision will be guided by the two goals of preserving the free status
-of all derivatives of our free software and of promoting the sharing
-and reuse of software generally.
-
- NO WARRANTY
-
- 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
-WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
-EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
-OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
-KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
-LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
-THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
- 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
-WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
-AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
-FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
-CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
-LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
-RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
-FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
-SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
-DAMAGES.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Libraries
-
- If you develop a new library, and you want it to be of the greatest
-possible use to the public, we recommend making it free software that
-everyone can redistribute and change. You can do so by permitting
-redistribution under these terms (or, alternatively, under the terms of the
-ordinary General Public License).
-
- To apply these terms, attach the following notices to the library. It is
-safest to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least the
-"copyright" line and a pointer to where the full notice is found.
-
- <one line to give the library's name and a brief idea of what it does.>
- Copyright (C) <year> <name of author>
-
- 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-
-Also add information on how to contact you by electronic and paper mail.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the library, if
-necessary. Here is a sample; alter the names:
-
- Yoyodyne, Inc., hereby disclaims all copyright interest in the
- library `Frob' (a library for tweaking knobs) written by James Random Hacker.
-
- <signature of Ty Coon>, 1 April 1990
- Ty Coon, President of Vice
-
-That's all there is to it!
-
-
diff --git a/android/apetag.mk b/android/apetag.mk
deleted file mode 100644
index 10ce6f95b..000000000
--- a/android/apetag.mk
+++ /dev/null
@@ -1,49 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_ARM_MODE := arm
-
-apetag_LOCAL_SRC_FILES:= \
- gst/apetag/gstapedemux.c
-
-LOCAL_SRC_FILES:= $(addprefix ../,$(apetag_LOCAL_SRC_FILES))
-
-LOCAL_SHARED_LIBRARIES := \
- libgstreamer-0.11 \
- libgstbase-0.11 \
- libglib-2.0 \
- libgthread-2.0 \
- libgmodule-2.0 \
- libgobject-2.0 \
- libgsttag-0.11 \
- libgstpbutils-0.11
-
-LOCAL_MODULE:= libgstapetag
-
-LOCAL_C_INCLUDES := \
- $(LOCAL_PATH)/../gst/apetag \
- $(LOCAL_PATH)/.. \
- $(LOCAL_PATH)/../gst-libs \
- $(LOCAL_PATH) \
- $(TARGET_OUT_HEADERS)/gstreamer-0.11 \
- $(TARGET_OUT_HEADERS)/glib-2.0 \
- $(TARGET_OUT_HEADERS)/glib-2.0/glib \
- external/libxml2/include
-
-
-ifeq ($(STECONF_ANDROID_VERSION),"FROYO")
-LOCAL_SHARED_LIBRARIES += libicuuc
-LOCAL_C_INCLUDES += external/icu4c/common
-endif
-
-LOCAL_CFLAGS := -DHAVE_CONFIG_H
-#
-# define LOCAL_PRELINK_MODULE to false to not use pre-link map
-#
-LOCAL_PRELINK_MODULE := false
-
-#It's a gstreamer plugins, and it must be installed on ..../lib/gstreamer-0.11
-LOCAL_MODULE_PATH := $(TARGET_OUT)/lib/gstreamer-0.11
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/android/avi.mk b/android/avi.mk
deleted file mode 100644
index 978fc062d..000000000
--- a/android/avi.mk
+++ /dev/null
@@ -1,51 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_ARM_MODE := arm
-
-avi_LOCAL_SRC_FILES:= \
- gst/avi/gstavi.c \
- gst/avi/gstavimux.c \
- gst/avi/gstavidemux.c \
- gst/avi/gstavisubtitle.c
-
-LOCAL_SRC_FILES:= $(addprefix ../,$(avi_LOCAL_SRC_FILES))
-
-LOCAL_SHARED_LIBRARIES := \
- libgstreamer-0.11 \
- libgstbase-0.11 \
- libglib-2.0 \
- libgthread-2.0 \
- libgmodule-2.0 \
- libgobject-2.0 \
- libgstriff-0.11
-
-LOCAL_MODULE:= libgstavi
-
-LOCAL_C_INCLUDES := \
- $(LOCAL_PATH)/../gst/avi \
- $(LOCAL_PATH)/.. \
- $(LOCAL_PATH)/../gst-libs \
- $(LOCAL_PATH)/ \
- $(LOCAL_PATH)/gst-libs/gst/audio \
- $(TARGET_OUT_HEADERS)/gstreamer-0.11 \
- $(TARGET_OUT_HEADERS)/glib-2.0 \
- $(TARGET_OUT_HEADERS)/glib-2.0/glib \
- external/libxml2/include
-
-ifeq ($(STECONF_ANDROID_VERSION),"FROYO")
-LOCAL_SHARED_LIBRARIES += libicuuc
-LOCAL_C_INCLUDES += external/icu4c/common
-endif
-
-LOCAL_CFLAGS := -DHAVE_CONFIG_H
-#
-# define LOCAL_PRELINK_MODULE to false to not use pre-link map
-#
-LOCAL_PRELINK_MODULE := false
-
-#It's a gstreamer plugins, and it must be installed on ..../lib/gstreamer-0.11
-LOCAL_MODULE_PATH := $(TARGET_OUT)/lib/gstreamer-0.11
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/android/flv.mk b/android/flv.mk
deleted file mode 100644
index 6c4bc75f0..000000000
--- a/android/flv.mk
+++ /dev/null
@@ -1,50 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_ARM_MODE := arm
-
-flv_LOCAL_SRC_FILES:= \
- gst/flv/gstflvdemux.c \
- gst/flv/gstflvparse.c \
- gst/flv/gstflvmux.c
-
-LOCAL_SRC_FILES:= $(addprefix ../,$(flv_LOCAL_SRC_FILES))
-
-LOCAL_SHARED_LIBRARIES := \
- libgstreamer-0.11 \
- libgstbase-0.11 \
- libglib-2.0 \
- libgthread-2.0 \
- libgmodule-2.0 \
- libgobject-2.0 \
- libgio-2.0 \
- libsoup-2.4
-
-LOCAL_MODULE:= libgstflv
-
-LOCAL_C_INCLUDES := \
- $(LOCAL_PATH)/../gst/flv \
- $(LOCAL_PATH)/.. \
- $(LOCAL_PATH)/../gst-libs \
- $(LOCAL_PATH) \
- $(TARGET_OUT_HEADERS)/gstreamer-0.11 \
- $(TARGET_OUT_HEADERS)/glib-2.0 \
- $(TARGET_OUT_HEADERS)/glib-2.0/glib \
- external/libxml2/include
-
-ifeq ($(STECONF_ANDROID_VERSION),"FROYO")
-LOCAL_SHARED_LIBRARIES += libicuuc
-LOCAL_C_INCLUDES += external/icu4c/common
-endif
-
-LOCAL_CFLAGS := -DHAVE_CONFIG_H
-#
-# define LOCAL_PRELINK_MODULE to false to not use pre-link map
-#
-LOCAL_PRELINK_MODULE := false
-
-#It's a gstreamer plugins, and it must be installed on ..../lib/gstreamer-0.11
-LOCAL_MODULE_PATH := $(TARGET_OUT)/lib/gstreamer-0.11
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/android/gst/rtpmanager/gstrtpbin-marshal.c b/android/gst/rtpmanager/gstrtpbin-marshal.c
deleted file mode 100644
index cde96cf81..000000000
--- a/android/gst/rtpmanager/gstrtpbin-marshal.c
+++ /dev/null
@@ -1,321 +0,0 @@
-#include "gstrtpbin-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 */
-
-
-/* UINT:UINT (gstrtpbin-marshal.list:1) */
-void
-gst_rtp_bin_marshal_UINT__UINT (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 guint (*GMarshalFunc_UINT__UINT) (gpointer data1,
- guint arg_1, gpointer data2);
- register GMarshalFunc_UINT__UINT callback;
- register GCClosure *cc = (GCClosure *) closure;
- register gpointer data1, data2;
- guint 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_UINT__UINT) (marshal_data ? marshal_data : cc->callback);
-
- v_return = callback (data1,
- g_marshal_value_peek_uint (param_values + 1), data2);
-
- g_value_set_uint (return_value, v_return);
-}
-
-/* BOXED:UINT (gstrtpbin-marshal.list:2) */
-void
-gst_rtp_bin_marshal_BOXED__UINT (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__UINT) (gpointer data1,
- guint arg_1, gpointer data2);
- register GMarshalFunc_BOXED__UINT callback;
- register GCClosure *cc = (GCClosure *) closure;
- register gpointer data1, data2;
- gpointer 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_BOXED__UINT) (marshal_data ? marshal_data : cc->callback);
-
- v_return = callback (data1,
- g_marshal_value_peek_uint (param_values + 1), data2);
-
- g_value_take_boxed (return_value, v_return);
-}
-
-/* BOXED:UINT,UINT (gstrtpbin-marshal.list:3) */
-void
-gst_rtp_bin_marshal_BOXED__UINT_UINT (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__UINT_UINT) (gpointer data1,
- guint arg_1, guint arg_2, gpointer data2);
- register GMarshalFunc_BOXED__UINT_UINT callback;
- register GCClosure *cc = (GCClosure *) closure;
- register gpointer data1, data2;
- gpointer 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_BOXED__UINT_UINT) (marshal_data ? marshal_data :
- cc->callback);
-
- v_return = callback (data1,
- g_marshal_value_peek_uint (param_values + 1),
- g_marshal_value_peek_uint (param_values + 2), data2);
-
- g_value_take_boxed (return_value, v_return);
-}
-
-/* OBJECT:UINT (gstrtpbin-marshal.list:4) */
-void
-gst_rtp_bin_marshal_OBJECT__UINT (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__UINT) (gpointer data1,
- guint arg_1, gpointer data2);
- register GMarshalFunc_OBJECT__UINT 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__UINT) (marshal_data ? marshal_data : cc->callback);
-
- v_return = callback (data1,
- g_marshal_value_peek_uint (param_values + 1), data2);
-
- g_value_take_object (return_value, v_return);
-}
-
-/* VOID:UINT,OBJECT (gstrtpbin-marshal.list:5) */
-void
-gst_rtp_bin_marshal_VOID__UINT_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 void (*GMarshalFunc_VOID__UINT_OBJECT) (gpointer data1,
- guint arg_1, gpointer arg_2, gpointer data2);
- register GMarshalFunc_VOID__UINT_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 =
- (GMarshalFunc_VOID__UINT_OBJECT) (marshal_data ? marshal_data :
- cc->callback);
-
- callback (data1,
- g_marshal_value_peek_uint (param_values + 1),
- g_marshal_value_peek_object (param_values + 2), data2);
-}
-
-/* VOID:UINT (gstrtpbin-marshal.list:6) */
-
-/* VOID:UINT,UINT (gstrtpbin-marshal.list:7) */
-void
-gst_rtp_bin_marshal_VOID__UINT_UINT (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__UINT_UINT) (gpointer data1,
- guint arg_1, guint arg_2, gpointer data2);
- register GMarshalFunc_VOID__UINT_UINT 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 =
- (GMarshalFunc_VOID__UINT_UINT) (marshal_data ? marshal_data :
- cc->callback);
-
- callback (data1,
- g_marshal_value_peek_uint (param_values + 1),
- g_marshal_value_peek_uint (param_values + 2), data2);
-}
-
-/* VOID:OBJECT,OBJECT (gstrtpbin-marshal.list:8) */
-void
-gst_rtp_bin_marshal_VOID__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)
-{
- typedef void (*GMarshalFunc_VOID__OBJECT_OBJECT) (gpointer data1,
- gpointer arg_1, gpointer arg_2, gpointer data2);
- register GMarshalFunc_VOID__OBJECT_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 =
- (GMarshalFunc_VOID__OBJECT_OBJECT) (marshal_data ? marshal_data :
- cc->callback);
-
- callback (data1,
- g_marshal_value_peek_object (param_values + 1),
- g_marshal_value_peek_object (param_values + 2), data2);
-}
-
-/* UINT64:BOOL,UINT64 (gstrtpbin-marshal.list:9) */
-void
-gst_rtp_bin_marshal_UINT64__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)
-{
- typedef guint64 (*GMarshalFunc_UINT64__BOOLEAN_UINT64) (gpointer data1,
- gboolean arg_1, guint64 arg_2, gpointer data2);
- register GMarshalFunc_UINT64__BOOLEAN_UINT64 callback;
- register GCClosure *cc = (GCClosure *) closure;
- register gpointer data1, data2;
- guint64 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_UINT64__BOOLEAN_UINT64) (marshal_data ? marshal_data :
- cc->callback);
-
- v_return = callback (data1,
- g_marshal_value_peek_boolean (param_values + 1),
- g_marshal_value_peek_uint64 (param_values + 2), data2);
-
- g_value_set_uint64 (return_value, v_return);
-}
diff --git a/android/gst/rtpmanager/gstrtpbin-marshal.h b/android/gst/rtpmanager/gstrtpbin-marshal.h
deleted file mode 100644
index da33b8fb5..000000000
--- a/android/gst/rtpmanager/gstrtpbin-marshal.h
+++ /dev/null
@@ -1,80 +0,0 @@
-
-#ifndef __gst_rtp_bin_marshal_MARSHAL_H__
-#define __gst_rtp_bin_marshal_MARSHAL_H__
-
-#include <glib-object.h>
-
-G_BEGIN_DECLS
-
-/* UINT:UINT (gstrtpbin-marshal.list:1) */
-extern void gst_rtp_bin_marshal_UINT__UINT (GClosure *closure,
- GValue *return_value,
- guint n_param_values,
- const GValue *param_values,
- gpointer invocation_hint,
- gpointer marshal_data);
-
-/* BOXED:UINT (gstrtpbin-marshal.list:2) */
-extern void gst_rtp_bin_marshal_BOXED__UINT (GClosure *closure,
- GValue *return_value,
- guint n_param_values,
- const GValue *param_values,
- gpointer invocation_hint,
- gpointer marshal_data);
-
-/* BOXED:UINT,UINT (gstrtpbin-marshal.list:3) */
-extern void gst_rtp_bin_marshal_BOXED__UINT_UINT (GClosure *closure,
- GValue *return_value,
- guint n_param_values,
- const GValue *param_values,
- gpointer invocation_hint,
- gpointer marshal_data);
-
-/* OBJECT:UINT (gstrtpbin-marshal.list:4) */
-extern void gst_rtp_bin_marshal_OBJECT__UINT (GClosure *closure,
- GValue *return_value,
- guint n_param_values,
- const GValue *param_values,
- gpointer invocation_hint,
- gpointer marshal_data);
-
-/* VOID:UINT,OBJECT (gstrtpbin-marshal.list:5) */
-extern void gst_rtp_bin_marshal_VOID__UINT_OBJECT (GClosure *closure,
- GValue *return_value,
- guint n_param_values,
- const GValue *param_values,
- gpointer invocation_hint,
- gpointer marshal_data);
-
-/* VOID:UINT (gstrtpbin-marshal.list:6) */
-#define gst_rtp_bin_marshal_VOID__UINT g_cclosure_marshal_VOID__UINT
-
-/* VOID:UINT,UINT (gstrtpbin-marshal.list:7) */
-extern void gst_rtp_bin_marshal_VOID__UINT_UINT (GClosure *closure,
- GValue *return_value,
- guint n_param_values,
- const GValue *param_values,
- gpointer invocation_hint,
- gpointer marshal_data);
-
-/* VOID:OBJECT,OBJECT (gstrtpbin-marshal.list:8) */
-extern void gst_rtp_bin_marshal_VOID__OBJECT_OBJECT (GClosure *closure,
- GValue *return_value,
- guint n_param_values,
- const GValue *param_values,
- gpointer invocation_hint,
- gpointer marshal_data);
-
-/* UINT64:BOOL,UINT64 (gstrtpbin-marshal.list:9) */
-extern void gst_rtp_bin_marshal_UINT64__BOOLEAN_UINT64 (GClosure *closure,
- GValue *return_value,
- guint n_param_values,
- const GValue *param_values,
- gpointer invocation_hint,
- gpointer marshal_data);
-#define gst_rtp_bin_marshal_UINT64__BOOL_UINT64 gst_rtp_bin_marshal_UINT64__BOOLEAN_UINT64
-
-G_END_DECLS
-
-#endif /* __gst_rtp_bin_marshal_MARSHAL_H__ */
-
diff --git a/android/gst/udp/gstudp-enumtypes.c b/android/gst/udp/gstudp-enumtypes.c
deleted file mode 100644
index 90501a43e..000000000
--- a/android/gst/udp/gstudp-enumtypes.c
+++ /dev/null
@@ -1,27 +0,0 @@
-
-/* Generated data (by glib-mkenums) */
-
-#include "gstudp-enumtypes.h"
-
-#include "gstudp.h"
-
-/* enumerations from "gstudp.h" */
-GType
-gst_udp_control_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[] = {
- {CONTROL_ZERO, "CONTROL_ZERO", "zero"},
- {CONTROL_NONE, "CONTROL_NONE", "none"},
- {CONTROL_UDP, "CONTROL_UDP", "udp"},
- {CONTROL_TCP, "CONTROL_TCP", "tcp"},
- {0, NULL, NULL}
- };
- GType g_define_type_id = g_enum_register_static ("GstUDPControl", values);
- g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
- }
- return g_define_type_id__volatile;
-}
-
-/* Generated data ends here */
diff --git a/android/gst/udp/gstudp-enumtypes.h b/android/gst/udp/gstudp-enumtypes.h
deleted file mode 100644
index 6b0697a96..000000000
--- a/android/gst/udp/gstudp-enumtypes.h
+++ /dev/null
@@ -1,19 +0,0 @@
-
-/* Generated data (by glib-mkenums) */
-
-#ifndef __GST_UDP_ENUM_TYPES_H__
-#define __GST_UDP_ENUM_TYPES_H__
-
-#include <glib-object.h>
-
-G_BEGIN_DECLS
-
-/* enumerations from "gstudp.h" */
-GType gst_udp_control_get_type (void);
-#define GST_TYPE_UDP_CONTROL (gst_udp_control_get_type())
-G_END_DECLS
-
-#endif /* __GST_UDP_ENUM_TYPES_H__ */
-
-/* Generated data ends here */
-
diff --git a/android/gst/udp/gstudp-marshal.c b/android/gst/udp/gstudp-marshal.c
deleted file mode 100644
index 42aa04c5a..000000000
--- a/android/gst/udp/gstudp-marshal.c
+++ /dev/null
@@ -1,117 +0,0 @@
-#include "gstudp-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 */
-
-
-/* VOID:STRING,INT (gstudp-marshal.list:1) */
-void
-gst_udp_marshal_VOID__STRING_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 void (*GMarshalFunc_VOID__STRING_INT) (gpointer data1,
- gpointer arg_1, gint arg_2, gpointer data2);
- register GMarshalFunc_VOID__STRING_INT 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 =
- (GMarshalFunc_VOID__STRING_INT) (marshal_data ? marshal_data :
- cc->callback);
-
- callback (data1,
- g_marshal_value_peek_string (param_values + 1),
- g_marshal_value_peek_int (param_values + 2), data2);
-}
-
-/* BOXED:STRING,INT (gstudp-marshal.list:2) */
-void
-gst_udp_marshal_BOXED__STRING_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 gpointer (*GMarshalFunc_BOXED__STRING_INT) (gpointer data1,
- gpointer arg_1, gint arg_2, gpointer data2);
- register GMarshalFunc_BOXED__STRING_INT callback;
- register GCClosure *cc = (GCClosure *) closure;
- register gpointer data1, data2;
- gpointer 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_BOXED__STRING_INT) (marshal_data ? marshal_data :
- cc->callback);
-
- v_return = callback (data1,
- g_marshal_value_peek_string (param_values + 1),
- g_marshal_value_peek_int (param_values + 2), data2);
-
- g_value_take_boxed (return_value, v_return);
-}
diff --git a/android/gst/udp/gstudp-marshal.h b/android/gst/udp/gstudp-marshal.h
deleted file mode 100644
index d103bc376..000000000
--- a/android/gst/udp/gstudp-marshal.h
+++ /dev/null
@@ -1,28 +0,0 @@
-
-#ifndef __gst_udp_marshal_MARSHAL_H__
-#define __gst_udp_marshal_MARSHAL_H__
-
-#include <glib-object.h>
-
-G_BEGIN_DECLS
-
-/* VOID:STRING,INT (gstudp-marshal.list:1) */
-extern void gst_udp_marshal_VOID__STRING_INT (GClosure *closure,
- GValue *return_value,
- guint n_param_values,
- const GValue *param_values,
- gpointer invocation_hint,
- gpointer marshal_data);
-
-/* BOXED:STRING,INT (gstudp-marshal.list:2) */
-extern void gst_udp_marshal_BOXED__STRING_INT (GClosure *closure,
- GValue *return_value,
- guint n_param_values,
- const GValue *param_values,
- gpointer invocation_hint,
- gpointer marshal_data);
-
-G_END_DECLS
-
-#endif /* __gst_udp_marshal_MARSHAL_H__ */
-
diff --git a/android/icydemux.mk b/android/icydemux.mk
deleted file mode 100644
index a491a6256..000000000
--- a/android/icydemux.mk
+++ /dev/null
@@ -1,47 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_ARM_MODE := arm
-
-icydemux_LOCAL_SRC_FILES:= \
- gst/icydemux/gsticydemux.c
-
-LOCAL_SRC_FILES:= $(addprefix ../,$(icydemux_LOCAL_SRC_FILES))
-
-LOCAL_SHARED_LIBRARIES := \
- libgstreamer-0.11 \
- libgstbase-0.11 \
- libglib-2.0 \
- libgthread-2.0 \
- libgmodule-2.0 \
- libgobject-2.0 \
- libgsttag-0.11
-
-LOCAL_MODULE:= libgsticydemux
-
-LOCAL_C_INCLUDES := \
- $(LOCAL_PATH)/../gst/icydemux \
- $(LOCAL_PATH)/.. \
- $(LOCAL_PATH)/../gst-libs \
- $(LOCAL_PATH) \
- $(TARGET_OUT_HEADERS)/gstreamer-0.11 \
- $(TARGET_OUT_HEADERS)/glib-2.0 \
- $(TARGET_OUT_HEADERS)/glib-2.0/glib \
- external/libxml2/include
-
-ifeq ($(STECONF_ANDROID_VERSION),"FROYO")
-LOCAL_SHARED_LIBRARIES += libicuuc
-LOCAL_C_INCLUDES += external/icu4c/common
-endif
-
-LOCAL_CFLAGS := -DHAVE_CONFIG_H
-#
-# define LOCAL_PRELINK_MODULE to false to not use pre-link map
-#
-LOCAL_PRELINK_MODULE := false
-
-#It's a gstreamer plugins, and it must be installed on ..../lib/gstreamer-0.11
-LOCAL_MODULE_PATH := $(TARGET_OUT)/lib/gstreamer-0.11
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/android/id3demux.mk b/android/id3demux.mk
deleted file mode 100644
index 610b65f57..000000000
--- a/android/id3demux.mk
+++ /dev/null
@@ -1,50 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_ARM_MODE := arm
-
-id3demux_LOCAL_SRC_FILES:= \
- gst/id3demux/gstid3demux.c \
- gst/id3demux/id3tags.c \
- gst/id3demux/id3v2frames.c
-
-LOCAL_SRC_FILES:= $(addprefix ../,$(id3demux_LOCAL_SRC_FILES))
-
-LOCAL_SHARED_LIBRARIES := \
- libgstreamer-0.11 \
- libgstbase-0.11 \
- libglib-2.0 \
- libgthread-2.0 \
- libgmodule-2.0 \
- libgobject-2.0 \
- libgsttag-0.11 \
- libgstpbutils-0.11
-
-LOCAL_MODULE:= libgstid3demux
-
-LOCAL_C_INCLUDES := \
- $(LOCAL_PATH)/../gst/id3demux \
- $(LOCAL_PATH)/.. \
- $(LOCAL_PATH)/../gst-libs \
- $(LOCAL_PATH) \
- $(TARGET_OUT_HEADERS)/gstreamer-0.11 \
- $(TARGET_OUT_HEADERS)/glib-2.0 \
- $(TARGET_OUT_HEADERS)/glib-2.0/glib \
- external/libxml2/include
-
-ifeq ($(STECONF_ANDROID_VERSION),"FROYO")
-LOCAL_SHARED_LIBRARIES += libicuuc
-LOCAL_C_INCLUDES += external/icu4c/common
-endif
-
-LOCAL_CFLAGS := -DHAVE_CONFIG_H
-#
-# define LOCAL_PRELINK_MODULE to false to not use pre-link map
-#
-LOCAL_PRELINK_MODULE := false
-
-#It's a gstreamer plugins, and it must be installed on ..../lib/gstreamer-0.11
-LOCAL_MODULE_PATH := $(TARGET_OUT)/lib/gstreamer-0.11
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/android/qtdemux.mk b/android/qtdemux.mk
deleted file mode 100644
index 7ef99eef8..000000000
--- a/android/qtdemux.mk
+++ /dev/null
@@ -1,54 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_ARM_MODE := arm
-
-qtdemux_LOCAL_SRC_FILES:= \
- gst/qtdemux/quicktime.c \
- gst/qtdemux/qtdemux.c \
- gst/qtdemux/qtdemux_types.c \
- gst/qtdemux/qtdemux_dump.c \
- gst/qtdemux/gstrtpxqtdepay.c
-
-LOCAL_SRC_FILES:= $(addprefix ../,$(qtdemux_LOCAL_SRC_FILES))
-
-LOCAL_SHARED_LIBRARIES := \
- libgstreamer-0.11 \
- libgstbase-0.11 \
- libglib-2.0 \
- libgthread-2.0 \
- libgmodule-2.0 \
- libgobject-2.0 \
- libgsttag-0.11 \
- libgstrtp-0.11 \
- libgstriff-0.11 \
- libgstaudio-0.11
-
-LOCAL_MODULE:= libgstqtdemux
-
-LOCAL_C_INCLUDES := \
- $(LOCAL_PATH)/../gst/qtdemux \
- $(LOCAL_PATH)/.. \
- $(LOCAL_PATH)/../gst-libs \
- $(LOCAL_PATH) \
- $(TARGET_OUT_HEADERS)/gstreamer-0.11 \
- $(TARGET_OUT_HEADERS)/glib-2.0 \
- $(TARGET_OUT_HEADERS)/glib-2.0/glib \
- external/libxml2/include
-
-ifeq ($(STECONF_ANDROID_VERSION),"FROYO")
-LOCAL_SHARED_LIBRARIES += libicuuc
-LOCAL_C_INCLUDES += external/icu4c/common
-endif
-
-LOCAL_CFLAGS := -DHAVE_CONFIG_H
-#
-# define LOCAL_PRELINK_MODULE to false to not use pre-link map
-#
-LOCAL_PRELINK_MODULE := false
-
-#It's a gstreamer plugins, and it must be installed on ..../lib/gstreamer-0.11
-LOCAL_MODULE_PATH := $(TARGET_OUT)/lib/gstreamer-0.11
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/android/rtp.mk b/android/rtp.mk
deleted file mode 100644
index 57dfc3a89..000000000
--- a/android/rtp.mk
+++ /dev/null
@@ -1,113 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_ARM_MODE := arm
-
-rtp_LOCAL_SRC_FILES:= \
- gst/rtp/fnv1hash.c \
- gst/rtp/gstrtp.c \
- gst/rtp/gstrtpchannels.c \
- gst/rtp/gstrtpdepay.c \
- gst/rtp/gstrtpac3depay.c \
- gst/rtp/gstrtpbvdepay.c \
- gst/rtp/gstrtpbvpay.c \
- gst/rtp/gstrtpceltdepay.c \
- gst/rtp/gstrtpceltpay.c \
- gst/rtp/gstrtpdvdepay.c \
- gst/rtp/gstrtpdvpay.c \
- gst/rtp/gstrtpilbcdepay.c \
- gst/rtp/gstrtpilbcpay.c \
- gst/rtp/gstrtpmpadepay.c \
- gst/rtp/gstrtpmpapay.c \
- gst/rtp/gstrtpmpvdepay.c \
- gst/rtp/gstrtpmpvpay.c \
- gst/rtp/gstrtppcmadepay.c \
- gst/rtp/gstrtppcmudepay.c \
- gst/rtp/gstrtppcmupay.c \
- gst/rtp/gstrtppcmapay.c \
- gst/rtp/gstrtpg723depay.c \
- gst/rtp/gstrtpg723pay.c \
- gst/rtp/gstrtpg726pay.c \
- gst/rtp/gstrtpg726depay.c \
- gst/rtp/gstrtpg729pay.c \
- gst/rtp/gstrtpg729depay.c \
- gst/rtp/gstrtpgsmdepay.c \
- gst/rtp/gstrtpgsmpay.c \
- gst/rtp/gstrtpamrdepay.c \
- gst/rtp/gstrtpamrpay.c \
- gst/rtp/gstrtph263pdepay.c \
- gst/rtp/gstrtph263ppay.c \
- gst/rtp/gstrtph263depay.c \
- gst/rtp/gstrtph263pay.c \
- gst/rtp/gstrtph264depay.c \
- gst/rtp/gstrtph264pay.c \
- gst/rtp/gstrtpj2kdepay.c \
- gst/rtp/gstrtpj2kpay.c \
- gst/rtp/gstrtpjpegdepay.c \
- gst/rtp/gstrtpjpegpay.c \
- gst/rtp/gstrtpL16depay.c \
- gst/rtp/gstrtpL16pay.c \
- gst/rtp/gstasteriskh263.c \
- gst/rtp/gstrtpmp1sdepay.c \
- gst/rtp/gstrtpmp2tdepay.c \
- gst/rtp/gstrtpmp2tpay.c \
- gst/rtp/gstrtpmp4vdepay.c \
- gst/rtp/gstrtpmp4vpay.c \
- gst/rtp/gstrtpmp4gdepay.c \
- gst/rtp/gstrtpmp4gpay.c \
- gst/rtp/gstrtpmp4adepay.c \
- gst/rtp/gstrtpmp4apay.c \
- gst/rtp/gstrtpqdmdepay.c \
- gst/rtp/gstrtpsirenpay.c \
- gst/rtp/gstrtpsirendepay.c \
- gst/rtp/gstrtpspeexdepay.c \
- gst/rtp/gstrtpspeexpay.c \
- gst/rtp/gstrtpsv3vdepay.c \
- gst/rtp/gstrtptheoradepay.c \
- gst/rtp/gstrtptheorapay.c \
- gst/rtp/gstrtpvorbisdepay.c \
- gst/rtp/gstrtpvorbispay.c \
- gst/rtp/gstrtpvrawdepay.c \
- gst/rtp/gstrtpvrawpay.c
-
-LOCAL_SRC_FILES:= $(addprefix ../,$(rtp_LOCAL_SRC_FILES))
-
-LOCAL_SHARED_LIBRARIES := \
- libgstreamer-0.11 \
- libgstbase-0.11 \
- libglib-2.0 \
- libgthread-2.0 \
- libgmodule-2.0 \
- libgobject-2.0 \
- libgsttag-0.11 \
- libgstrtp-0.11 \
- libgstaudio-0.11
-
-LOCAL_MODULE:= libgstrtp
-
-LOCAL_C_INCLUDES := \
- $(LOCAL_PATH)/../gst/rtp \
- $(LOCAL_PATH)/.. \
- $(LOCAL_PATH)/../gst-libs \
- $(LOCAL_PATH) \
- $(TARGET_OUT_HEADERS)/gstreamer-0.11 \
- $(TARGET_OUT_HEADERS)/glib-2.0 \
- $(TARGET_OUT_HEADERS)/glib-2.0/glib \
- external/libxml2/include
-
-ifeq ($(STECONF_ANDROID_VERSION),"FROYO")
-LOCAL_SHARED_LIBRARIES += libicuuc
-LOCAL_C_INCLUDES += external/icu4c/common
-endif
-
-LOCAL_CFLAGS := -DHAVE_CONFIG_H
-#
-# define LOCAL_PRELINK_MODULE to false to not use pre-link map
-#
-LOCAL_PRELINK_MODULE := false
-
-#It's a gstreamer plugins, and it must be installed on ..../lib/gstreamer-0.11
-LOCAL_MODULE_PATH := $(TARGET_OUT)/lib/gstreamer-0.11
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/android/rtpmanager.mk b/android/rtpmanager.mk
deleted file mode 100644
index 148a4cd6e..000000000
--- a/android/rtpmanager.mk
+++ /dev/null
@@ -1,61 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_ARM_MODE := arm
-
-rtpmanager_LOCAL_SRC_FILES_BASE:= \
- gst/rtpmanager/gstrtpmanager.c \
- gst/rtpmanager/gstrtpbin.c \
- gst/rtpmanager/gstrtpjitterbuffer.c \
- gst/rtpmanager/gstrtpptdemux.c \
- gst/rtpmanager/gstrtpssrcdemux.c \
- gst/rtpmanager/rtpjitterbuffer.c \
- gst/rtpmanager/rtpsession.c \
- gst/rtpmanager/rtpsource.c \
- gst/rtpmanager/rtpstats.c \
- gst/rtpmanager/gstrtpsession.c
-rtpmanager_LOCAL_SRC_FILES_ANDROID:= \
- gst/rtpmanager/gstrtpbin-marshal.c
-
-LOCAL_SRC_FILES:= $(addprefix ../,$(rtpmanager_LOCAL_SRC_FILES_BASE)) \
- $(addprefix ../android/,$(rtpmanager_LOCAL_SRC_FILES_ANDROID))
-
-LOCAL_SHARED_LIBRARIES := \
- libgstreamer-0.11 \
- libgstbase-0.11 \
- libglib-2.0 \
- libgthread-2.0 \
- libgmodule-2.0 \
- libgobject-2.0 \
- libgstnetbuffer-0.11 \
- libgstrtp-0.11
-
-LOCAL_MODULE:= libgstrtpmanager
-
-LOCAL_C_INCLUDES := \
- $(LOCAL_PATH)/../gst/rtpmanager \
- $(LOCAL_PATH)/.. \
- $(LOCAL_PATH)/../gst-libs \
- $(LOCAL_PATH) \
- $(LOCAL_PATH)/gst/rtpmanager \
- $(TARGET_OUT_HEADERS)/gstreamer-0.11 \
- $(TARGET_OUT_HEADERS)/glib-2.0 \
- $(TARGET_OUT_HEADERS)/glib-2.0/glib \
- external/libxml2/include
-
-ifeq ($(STECONF_ANDROID_VERSION),"FROYO")
-LOCAL_SHARED_LIBRARIES += libicuuc
-LOCAL_C_INCLUDES += external/icu4c/common
-endif
-
-LOCAL_CFLAGS := -DHAVE_CONFIG_H
-#
-# define LOCAL_PRELINK_MODULE to false to not use pre-link map
-#
-LOCAL_PRELINK_MODULE := false
-
-#It's a gstreamer plugins, and it must be installed on ..../lib/gstreamer-0.11
-LOCAL_MODULE_PATH := $(TARGET_OUT)/lib/gstreamer-0.11
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/android/rtsp.mk b/android/rtsp.mk
deleted file mode 100644
index 29f890672..000000000
--- a/android/rtsp.mk
+++ /dev/null
@@ -1,53 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_ARM_MODE := arm
-
-rtsp_LOCAL_SRC_FILES:= \
- gst/rtsp/gstrtsp.c \
- gst/rtsp/gstrtspsrc.c \
- gst/rtsp/gstrtpdec.c \
- gst/rtsp/gstrtspext.c
-
-LOCAL_SRC_FILES:= $(addprefix ../,$(rtsp_LOCAL_SRC_FILES))
-
-LOCAL_SHARED_LIBRARIES := \
- libgstreamer-0.11 \
- libgstbase-0.11 \
- libglib-2.0 \
- libgthread-2.0 \
- libgmodule-2.0 \
- libgobject-2.0 \
- libgstrtp-0.11 \
- libgstinterfaces-0.11 \
- libgstrtsp-0.11 \
- libgstsdp-0.11
-
-LOCAL_MODULE:= libgstrtsp
-
-LOCAL_C_INCLUDES := \
- $(LOCAL_PATH)/../gst/rtsp \
- $(LOCAL_PATH)/.. \
- $(LOCAL_PATH)/../gst-libs \
- $(LOCAL_PATH) \
- $(TARGET_OUT_HEADERS)/gstreamer-0.11 \
- $(TARGET_OUT_HEADERS)/glib-2.0 \
- $(TARGET_OUT_HEADERS)/glib-2.0/glib \
- external/libxml2/include
-
-ifeq ($(STECONF_ANDROID_VERSION),"FROYO")
-LOCAL_SHARED_LIBRARIES += libicuuc
-LOCAL_C_INCLUDES += external/icu4c/common
-endif
-
-LOCAL_CFLAGS := -DHAVE_CONFIG_H
-#
-# define LOCAL_PRELINK_MODULE to false to not use pre-link map
-#
-LOCAL_PRELINK_MODULE := false
-
-#It's a gstreamer plugins, and it must be installed on ..../lib/gstreamer-0.11
-LOCAL_MODULE_PATH := $(TARGET_OUT)/lib/gstreamer-0.11
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/android/soup.mk b/android/soup.mk
deleted file mode 100644
index 29d9d1452..000000000
--- a/android/soup.mk
+++ /dev/null
@@ -1,49 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_ARM_MODE := arm
-
-soup_LOCAL_SRC_FILES:= \
- ext/soup/gstsouphttpsrc.c
-
-LOCAL_SRC_FILES:= $(addprefix ../,$(soup_LOCAL_SRC_FILES))
-
-LOCAL_SHARED_LIBRARIES := \
- libgstreamer-0.11 \
- libgstbase-0.11 \
- libglib-2.0 \
- libgthread-2.0 \
- libgmodule-2.0 \
- libgobject-2.0 \
- libgsttag-0.11 \
- libsoup-2.4
-
-LOCAL_MODULE:= libgstsouphttpsrc
-
-LOCAL_C_INCLUDES := \
- $(LOCAL_PATH)/../ext/soup \
- $(LOCAL_PATH)/.. \
- $(LOCAL_PATH)/../gst-libs \
- $(LOCAL_PATH) \
- $(TARGET_OUT_HEADERS)/gstreamer-0.11 \
- $(TARGET_OUT_HEADERS)/glib-2.0 \
- $(TARGET_OUT_HEADERS)/glib-2.0/glib \
- external/libxml2/include \
- $(TARGET_OUT_HEADERS)/libsoup-2.4
-
-ifeq ($(STECONF_ANDROID_VERSION),"FROYO")
-LOCAL_SHARED_LIBRARIES += libicuuc
-LOCAL_C_INCLUDES += external/icu4c/common
-endif
-
-LOCAL_CFLAGS := -DHAVE_CONFIG_H
-#
-# define LOCAL_PRELINK_MODULE to false to not use pre-link map
-#
-LOCAL_PRELINK_MODULE := false
-
-#It's a gstreamer plugins, and it must be installed on ..../lib/gstreamer-0.11
-LOCAL_MODULE_PATH := $(TARGET_OUT)/lib/gstreamer-0.11
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/android/udp.mk b/android/udp.mk
deleted file mode 100644
index 6a522bcad..000000000
--- a/android/udp.mk
+++ /dev/null
@@ -1,58 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_ARM_MODE := arm
-
-udp_LOCAL_SRC_FILES_BASE:= \
- gst/udp/gstudp.c \
- gst/udp/gstudpsrc.c \
- gst/udp/gstudpsink.c \
- gst/udp/gstmultiudpsink.c \
- gst/udp/gstdynudpsink.c \
- gst/udp/gstudpnetutils.c
-udp_LOCAL_SRC_FILES_ANDROID:= \
- gst/udp/gstudp-enumtypes.c \
- gst/udp/gstudp-marshal.c
-
-LOCAL_SRC_FILES:= $(addprefix ../,$(udp_LOCAL_SRC_FILES_BASE)) \
- $(addprefix ../android/,$(udp_LOCAL_SRC_FILES_ANDROID))
-
-LOCAL_SHARED_LIBRARIES := \
- libgstreamer-0.11 \
- libgstbase-0.11 \
- libglib-2.0 \
- libgthread-2.0 \
- libgmodule-2.0 \
- libgobject-2.0 \
- libgsttag-0.11 \
- libgstnetbuffer-0.11
-
-LOCAL_MODULE:= libgstudp
-
-LOCAL_C_INCLUDES := \
- $(LOCAL_PATH)/../gst/udp \
- $(LOCAL_PATH)/.. \
- $(LOCAL_PATH)/../gst-libs \
- $(LOCAL_PATH) \
- $(LOCAL_PATH)/gst/udp \
- $(TARGET_OUT_HEADERS)/gstreamer-0.11 \
- $(TARGET_OUT_HEADERS)/glib-2.0 \
- $(TARGET_OUT_HEADERS)/glib-2.0/glib \
- external/libxml2/include
-
-ifeq ($(STECONF_ANDROID_VERSION),"FROYO")
-LOCAL_SHARED_LIBRARIES += libicuuc
-LOCAL_C_INCLUDES += external/icu4c/common
-endif
-
-LOCAL_CFLAGS := -DHAVE_CONFIG_H -DGSTREAMER_BUILT_FOR_ANDROID
-#
-# define LOCAL_PRELINK_MODULE to false to not use pre-link map
-#
-LOCAL_PRELINK_MODULE := false
-
-#It's a gstreamer plugins, and it must be installed on ..../lib/gstreamer-0.11
-LOCAL_MODULE_PATH := $(TARGET_OUT)/lib/gstreamer-0.11
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/android/wavenc.mk b/android/wavenc.mk
deleted file mode 100644
index 5ba776908..000000000
--- a/android/wavenc.mk
+++ /dev/null
@@ -1,47 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_ARM_MODE := arm
-
-wavenc_LOCAL_SRC_FILES:= \
- gst/wavenc/gstwavenc.c
-
-LOCAL_SRC_FILES:= $(addprefix ../,$(wavenc_LOCAL_SRC_FILES))
-
-LOCAL_SHARED_LIBRARIES := \
- libgstreamer-0.11 \
- libgstbase-0.11 \
- libglib-2.0 \
- libgthread-2.0 \
- libgmodule-2.0 \
- libgobject-2.0 \
- libgstriff-0.11
-
-LOCAL_MODULE:= libgstwavenc
-
-LOCAL_C_INCLUDES := \
- $(LOCAL_PATH)/../gst/wavenc \
- $(LOCAL_PATH)/.. \
- $(LOCAL_PATH)/../gst-libs \
- $(LOCAL_PATH) \
- $(TARGET_OUT_HEADERS)/gstreamer-0.11 \
- $(TARGET_OUT_HEADERS)/glib-2.0 \
- $(TARGET_OUT_HEADERS)/glib-2.0/glib \
- external/libxml2/include
-
-ifeq ($(STECONF_ANDROID_VERSION),"FROYO")
-LOCAL_SHARED_LIBRARIES += libicuuc
-LOCAL_C_INCLUDES += external/icu4c/common
-endif
-
-LOCAL_CFLAGS := -DHAVE_CONFIG_H
-#
-# define LOCAL_PRELINK_MODULE to false to not use pre-link map
-#
-LOCAL_PRELINK_MODULE := false
-
-#It's a gstreamer plugins, and it must be installed on ..../lib/gstreamer-0.11
-LOCAL_MODULE_PATH := $(TARGET_OUT)/lib/gstreamer-0.11
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/android/wavparse.mk b/android/wavparse.mk
deleted file mode 100644
index d10a7b090..000000000
--- a/android/wavparse.mk
+++ /dev/null
@@ -1,47 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_ARM_MODE := arm
-
-wavparse_LOCAL_SRC_FILES:= \
- gst/wavparse/gstwavparse.c
-
-LOCAL_SRC_FILES:= $(addprefix ../,$(wavparse_LOCAL_SRC_FILES))
-
-LOCAL_SHARED_LIBRARIES := \
- libgstreamer-0.11 \
- libgstbase-0.11 \
- libglib-2.0 \
- libgthread-2.0 \
- libgmodule-2.0 \
- libgobject-2.0 \
- libgstriff-0.11
-
-LOCAL_MODULE:= libgstwavparse
-
-LOCAL_C_INCLUDES := \
- $(LOCAL_PATH)/../gst/wavparse \
- $(LOCAL_PATH)/.. \
- $(LOCAL_PATH)/../gst-libs \
- $(LOCAL_PATH) \
- $(TARGET_OUT_HEADERS)/gstreamer-0.11 \
- $(TARGET_OUT_HEADERS)/glib-2.0 \
- $(TARGET_OUT_HEADERS)/glib-2.0/glib \
- external/libxml2/include
-
-ifeq ($(STECONF_ANDROID_VERSION),"FROYO")
-LOCAL_SHARED_LIBRARIES += libicuuc
-LOCAL_C_INCLUDES += external/icu4c/common
-endif
-
-LOCAL_CFLAGS := -DHAVE_CONFIG_H
-#
-# define LOCAL_PRELINK_MODULE to false to not use pre-link map
-#
-LOCAL_PRELINK_MODULE := false
-
-#It's a gstreamer plugins, and it must be installed on ..../lib/gstreamer-0.11
-LOCAL_MODULE_PATH := $(TARGET_OUT)/lib/gstreamer-0.11
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/configure.ac b/configure.ac
index 2388b417d..d3f4c4efb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -323,6 +323,7 @@ AG_GST_CHECK_PLUGIN(videofilter)
AG_GST_CHECK_PLUGIN(alpha)
AG_GST_CHECK_PLUGIN(apetag)
AG_GST_CHECK_PLUGIN(audiofx)
+AG_GST_CHECK_PLUGIN(audioparsers)
AG_GST_CHECK_PLUGIN(auparse)
AG_GST_CHECK_PLUGIN(autodetect)
AG_GST_CHECK_PLUGIN(avi)
@@ -345,7 +346,7 @@ AG_GST_CHECK_PLUGIN(matroska)
AG_GST_CHECK_PLUGIN(monoscope)
AG_GST_CHECK_PLUGIN(multifile)
AG_GST_CHECK_PLUGIN(multipart)
-AG_GST_CHECK_PLUGIN(qtdemux)
+AG_GST_CHECK_PLUGIN(quicktime)
AG_GST_CHECK_PLUGIN(replaygain)
AG_GST_CHECK_PLUGIN(rtp)
AG_GST_CHECK_PLUGIN(rtpmanager)
@@ -767,11 +768,14 @@ AG_GST_CHECK_FEATURE(JACK, Jack, jack, [
AC_SUBST(JACK_CFLAGS)
AC_SUBST(JACK_LIBS)
- dnl upcomming jack2 (1.9.7 will have the new api as well
AG_GST_PKG_CHECK_MODULES(JACK_0_120_1, jack >= 0.120.1 jack < 1.0)
if test x$HAVE_JACK_0_120_1 = xyes; then
AC_DEFINE(HAVE_JACK_0_120_1, 1, [defined if jack >= 0.120.1 is available])
fi
+ AG_GST_PKG_CHECK_MODULES(JACK_1_9_7, jack >= 1.9.7)
+ if test x$HAVE_JACK_1_9_7 = xyes; then
+ AC_DEFINE(HAVE_JACK_1_9_7, 1, [defined if jack >= 1.9.7 is available])
+ fi
])
@@ -1133,6 +1137,7 @@ gst/Makefile
gst/alpha/Makefile
gst/apetag/Makefile
gst/audiofx/Makefile
+gst/audioparsers/Makefile
gst/auparse/Makefile
gst/autodetect/Makefile
gst/avi/Makefile
@@ -1154,7 +1159,7 @@ gst/matroska/Makefile
gst/monoscope/Makefile
gst/multifile/Makefile
gst/multipart/Makefile
-gst/qtdemux/Makefile
+gst/quicktime/Makefile
gst/replaygain/Makefile
gst/rtp/Makefile
gst/rtpmanager/Makefile
diff --git a/docs/plugins/Makefile.am b/docs/plugins/Makefile.am
index 491034979..b511a43f7 100644
--- a/docs/plugins/Makefile.am
+++ b/docs/plugins/Makefile.am
@@ -132,6 +132,12 @@ EXTRA_HFILES = \
$(top_srcdir)/gst/audiofx/audiowsincband.h \
$(top_srcdir)/gst/audiofx/audiowsinclimit.h \
$(top_srcdir)/gst/audiofx/audiofirfilter.h \
+ $(top_srcdir)/gst/audioparsers/gstaacparse.h \
+ $(top_srcdir)/gst/audioparsers/gstac3parse.h \
+ $(top_srcdir)/gst/audioparsers/gstamrparse.h \
+ $(top_srcdir)/gst/audioparsers/gstflacparse.h \
+ $(top_srcdir)/gst/audioparsers/gstdcaparse.h \
+ $(top_srcdir)/gst/audioparsers/gstmpegaudioparse.h \
$(top_srcdir)/gst/auparse/gstauparse.h \
$(top_srcdir)/gst/autodetect/gstautoaudiosink.h \
$(top_srcdir)/gst/autodetect/gstautoaudiosrc.h \
@@ -184,7 +190,8 @@ EXTRA_HFILES = \
$(top_srcdir)/gst/multifile/gstmultifilesrc.h \
$(top_srcdir)/gst/multipart/multipartdemux.h \
$(top_srcdir)/gst/multipart/multipartmux.h \
- $(top_srcdir)/gst/qtdemux/qtdemux.h \
+ $(top_srcdir)/gst/quicktime/qtdemux.h \
+ $(top_srcdir)/gst/quicktime/gstqtmux.h \
$(top_srcdir)/gst/replaygain/gstrganalysis.h \
$(top_srcdir)/gst/replaygain/gstrglimiter.h \
$(top_srcdir)/gst/replaygain/gstrgvolume.h \
diff --git a/docs/plugins/gst-plugins-good-plugins-docs.sgml b/docs/plugins/gst-plugins-good-plugins-docs.sgml
index 988bba341..fba35fd88 100644
--- a/docs/plugins/gst-plugins-good-plugins-docs.sgml
+++ b/docs/plugins/gst-plugins-good-plugins-docs.sgml
@@ -18,12 +18,15 @@
<chapter>
<title>gst-plugins-good Elements</title>
+ <xi:include href="xml/element-aacparse.xml" />
<xi:include href="xml/element-aasink.xml" />
+ <xi:include href="xml/element-ac3parse.xml" />
<xi:include href="xml/element-agingtv.xml" />
<xi:include href="xml/element-alpha.xml" />
<xi:include href="xml/element-alphacolor.xml" />
<xi:include href="xml/element-alawdec.xml" />
<xi:include href="xml/element-alawenc.xml" />
+ <xi:include href="xml/element-amrparse.xml" />
<xi:include href="xml/element-apedemux.xml" />
<xi:include href="xml/element-apev2mux.xml" />
<xi:include href="xml/element-aspectratiocrop.xml" />
@@ -56,6 +59,7 @@
<xi:include href="xml/element-cmmldec.xml" />
<xi:include href="xml/element-cmmlenc.xml" />
<xi:include href="xml/element-cutter.xml" />
+ <xi:include href="xml/element-dcaparse.xml" />
<xi:include href="xml/element-deinterlace.xml" />
<xi:include href="xml/element-deinterleave.xml" />
<xi:include href="xml/element-dicetv.xml" />
@@ -70,6 +74,7 @@
<xi:include href="xml/element-esdsink.xml" />
<xi:include href="xml/element-flacdec.xml" />
<xi:include href="xml/element-flacenc.xml" />
+ <xi:include href="xml/element-flacparse.xml" />
<xi:include href="xml/element-flactag.xml" />
<xi:include href="xml/element-flvdemux.xml" />
<xi:include href="xml/element-flvmux.xml" />
@@ -103,6 +108,7 @@
<xi:include href="xml/element-matroskamux.xml" />
<xi:include href="xml/element-matroskademux.xml" />
<xi:include href="xml/element-monoscope.xml" />
+ <xi:include href="xml/element-mpegaudioparse.xml" />
<xi:include href="xml/element-mulawdec.xml" />
<xi:include href="xml/element-mulawenc.xml" />
<xi:include href="xml/element-multifilesink.xml" />
@@ -128,6 +134,7 @@
<xi:include href="xml/element-pulsemixer.xml" />
<xi:include href="xml/element-quarktv.xml" />
<xi:include href="xml/element-qtdemux.xml" />
+ <xi:include href="xml/element-qtmux.xml" />
<xi:include href="xml/element-radioactv.xml" />
<xi:include href="xml/element-revtv.xml" />
<xi:include href="xml/element-rganalysis.xml" />
diff --git a/docs/plugins/gst-plugins-good-plugins-sections.txt b/docs/plugins/gst-plugins-good-plugins-sections.txt
index b2e6de68c..d2b8f759e 100644
--- a/docs/plugins/gst-plugins-good-plugins-sections.txt
+++ b/docs/plugins/gst-plugins-good-plugins-sections.txt
@@ -1,4 +1,18 @@
<SECTION>
+<FILE>element-aacparse</FILE>
+<TITLE>aacparse</TITLE>
+GstAacParse
+<SUBSECTION Standard>
+GstAacParseClass
+GST_AAC_PARSE
+GST_AAC_PARSE_CLASS
+GST_IS_AAC_PARSE
+GST_IS_AAC_PARSE_CLASS
+GST_TYPE_AAC_PARSE
+gst_aac_parse_get_type
+</SECTION>
+
+<SECTION>
<FILE>element-aasink</FILE>
<TITLE>aasink</TITLE>
GstAASink
@@ -13,6 +27,20 @@ gst_aasink_get_type
</SECTION>
<SECTION>
+<FILE>element-ac3parse</FILE>
+<TITLE>ac3parse</TITLE>
+GstAc3Parse
+<SUBSECTION Standard>
+GstAc3ParseClass
+GST_AC3_PARSE
+GST_AC3_PARSE_CLASS
+GST_IS_AC3_PARSE
+GST_IS_AC3_PARSE_CLASS
+GST_TYPE_AC3_PARSE
+gst_ac3_parse_get_type
+</SECTION>
+
+<SECTION>
<FILE>element-alawdec</FILE>
<TITLE>alawdec</TITLE>
GstALawDec
@@ -69,6 +97,20 @@ GST_IS_ALPHA_COLOR_CLASS
</SECTION>
<SECTION>
+<FILE>element-amrparse</FILE>
+<TITLE>amrparse</TITLE>
+GstAmrParse
+<SUBSECTION Standard>
+GstAmrParseClass
+GST_AMR_PARSE
+GST_AMR_PARSE_CLASS
+GST_IS_AMR_PARSE
+GST_IS_AMR_PARSE_CLASS
+GST_TYPE_AMR_PARSE
+gst_amr_parse_get_type
+</SECTION>
+
+<SECTION>
<FILE>element-apedemux</FILE>
<TITLE>apedemux</TITLE>
GstApeDemux
@@ -538,6 +580,21 @@ gst_cutter_get_type
</SECTION>
<SECTION>
+<FILE>element-dcaparse</FILE>
+<TITLE>dcaparse</TITLE>
+GstDcaParse
+<SUBSECTION Standard>
+GstDcaParseClass
+GST_DCA_PARSE
+GST_DCA_PARSE_CLASS
+GST_IS_DCA_PARSE
+GST_IS_DCA_PARSE_CLASS
+GST_TYPE_DCA_PARSE
+gst_dca_parse_get_type
+</SECTION>
+
+
+<SECTION>
<FILE>element-deinterlace</FILE>
<TITLE>deinterlace</TITLE>
GstDeinterlace
@@ -777,6 +834,20 @@ gst_flac_enc_get_type
</SECTION>
<SECTION>
+<FILE>element-flacparse</FILE>
+<TITLE>flacparse</TITLE>
+GstFlacParse
+<SUBSECTION Standard>
+GstFlacParseClass
+GST_FLAC_PARSE
+GST_FLAC_PARSE_CLASS
+GST_IS_FLAC_PARSE
+GST_IS_FLAC_PARSE_CLASS
+GST_TYPE_FLAC_PARSE
+gst_flac_parse_get_type
+</SECTION>
+
+<SECTION>
<FILE>element-flactag</FILE>
<TITLE>flactag</TITLE>
GstFlacTag
@@ -1244,6 +1315,20 @@ gst_monoscope_get_type
</SECTION>
<SECTION>
+<FILE>element-mpegaudioparse</FILE>
+<TITLE>mpegaudioparse</TITLE>
+GstMpegAudioParse
+<SUBSECTION Standard>
+GstMpegAudioParseClass
+GST_MPEG_AUDIO_PARSE
+GST_MPEG_AUDIO_PARSE_CLASS
+GST_IS_MPEG_AUDIO_PARSE
+GST_IS_MPEG_AUDIO_PARSE_CLASS
+GST_TYPE_MPEG_AUDIO_PARSE
+gst_mpeg_audio_parse_get_type
+</SECTION>
+
+<SECTION>
<FILE>element-mulawdec</FILE>
<TITLE>mulawdec</TITLE>
GstMuLawDec
@@ -1603,6 +1688,20 @@ gst_qtdemux_get_type
</SECTION>
<SECTION>
+<FILE>element-qtmux</FILE>
+<TITLE>qtmux</TITLE>
+GstQTMux
+<SUBSECTION Standard>
+GstQTMuxClass
+GST_QT_MUX
+GST_QT_MUX_CLASS
+GST_IS_QT_MUX
+GST_IS_QT_MUX_CLASS
+GST_TYPE_QT_MUX
+gst_qt_mux_get_type
+</SECTION>
+
+<SECTION>
<FILE>element-rganalysis</FILE>
<TITLE>rganalysis</TITLE>
GstRgAnalysis
diff --git a/docs/plugins/gst-plugins-good-plugins.args b/docs/plugins/gst-plugins-good-plugins.args
index 27b278877..a6143ee23 100644
--- a/docs/plugins/gst-plugins-good-plugins.args
+++ b/docs/plugins/gst-plugins-good-plugins.args
@@ -299,6 +299,16 @@
</ARG>
<ARG>
+<NAME>GstSpectrum::multi-channel</NAME>
+<TYPE>gboolean</TYPE>
+<RANGE></RANGE>
+<FLAGS>rw</FLAGS>
+<NICK>Multichannel results</NICK>
+<BLURB>Send separate results for each channel.</BLURB>
+<DEFAULT>FALSE</DEFAULT>
+</ARG>
+
+<ARG>
<NAME>GstVideoflip::method</NAME>
<TYPE>GstVideoflipMethod</TYPE>
<RANGE></RANGE>
@@ -3510,7 +3520,7 @@
<ARG>
<NAME>GstSoupHTTPSrc::cookies</NAME>
-<TYPE>GStrv*</TYPE>
+<TYPE>GStrv</TYPE>
<RANGE></RANGE>
<FLAGS>rw</FLAGS>
<NICK>Cookies</NICK>
@@ -21208,3 +21218,523 @@
<DEFAULT>NULL</DEFAULT>
</ARG>
+<ARG>
+<NAME>GstFlacParse::check-frame-checksums</NAME>
+<TYPE>gboolean</TYPE>
+<RANGE></RANGE>
+<FLAGS>rw</FLAGS>
+<NICK>Check Frame Checksums</NICK>
+<BLURB>Check the overall checksums of every frame.</BLURB>
+<DEFAULT>FALSE</DEFAULT>
+</ARG>
+
+<ARG>
+<NAME>GstV4l2Radio::device</NAME>
+<TYPE>gchar*</TYPE>
+<RANGE></RANGE>
+<FLAGS>rw</FLAGS>
+<NICK>Radio device location</NICK>
+<BLURB>Video4Linux2 radio device location.</BLURB>
+<DEFAULT>"/dev/radio0"</DEFAULT>
+</ARG>
+
+<ARG>
+<NAME>GstV4l2Radio::frequency</NAME>
+<TYPE>gint</TYPE>
+<RANGE>[87500000,108000000]</RANGE>
+<FLAGS>rw</FLAGS>
+<NICK>Station frequency</NICK>
+<BLURB>Station frequency in Hz.</BLURB>
+<DEFAULT>100000000</DEFAULT>
+</ARG>
+
+<ARG>
+<NAME>GstQTMux::dts-method</NAME>
+<TYPE>GstQTMuxDtsMethods</TYPE>
+<RANGE></RANGE>
+<FLAGS>rwx</FLAGS>
+<NICK>dts-method</NICK>
+<BLURB>Method to determine DTS time.</BLURB>
+<DEFAULT>reorder</DEFAULT>
+</ARG>
+
+<ARG>
+<NAME>GstQTMux::faststart</NAME>
+<TYPE>gboolean</TYPE>
+<RANGE></RANGE>
+<FLAGS>rw</FLAGS>
+<NICK>Format file to faststart</NICK>
+<BLURB>If the file should be formatted for faststart (headers first).</BLURB>
+<DEFAULT>FALSE</DEFAULT>
+</ARG>
+
+<ARG>
+<NAME>GstQTMux::faststart-file</NAME>
+<TYPE>gchar*</TYPE>
+<RANGE></RANGE>
+<FLAGS>rwx</FLAGS>
+<NICK>File to use for storing buffers</NICK>
+<BLURB>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.</BLURB>
+<DEFAULT>NULL</DEFAULT>
+</ARG>
+
+<ARG>
+<NAME>GstQTMux::fragment-duration</NAME>
+<TYPE>guint</TYPE>
+<RANGE></RANGE>
+<FLAGS>rwx</FLAGS>
+<NICK>Fragment duration</NICK>
+<BLURB>Fragment durations in ms (produce a fragmented file if > 0).</BLURB>
+<DEFAULT>0</DEFAULT>
+</ARG>
+
+<ARG>
+<NAME>GstQTMux::moov-recovery-file</NAME>
+<TYPE>gchar*</TYPE>
+<RANGE></RANGE>
+<FLAGS>rwx</FLAGS>
+<NICK>File to store data for posterior moov atom recovery</NICK>
+<BLURB>File to be used to store data for moov atom making movie file recovery possible in case of a crash during muxing. Null for disabled. (Experimental).</BLURB>
+<DEFAULT>NULL</DEFAULT>
+</ARG>
+
+<ARG>
+<NAME>GstQTMux::movie-timescale</NAME>
+<TYPE>guint</TYPE>
+<RANGE>>= 1</RANGE>
+<FLAGS>rwx</FLAGS>
+<NICK>Movie timescale</NICK>
+<BLURB>Timescale to use in the movie (units per second).</BLURB>
+<DEFAULT>1000</DEFAULT>
+</ARG>
+
+<ARG>
+<NAME>GstQTMux::presentation-time</NAME>
+<TYPE>gboolean</TYPE>
+<RANGE></RANGE>
+<FLAGS>rwx</FLAGS>
+<NICK>Include presentation-time info</NICK>
+<BLURB>Calculate and include presentation/composition time (in addition to decoding time).</BLURB>
+<DEFAULT>TRUE</DEFAULT>
+</ARG>
+
+<ARG>
+<NAME>GstQTMux::streamable</NAME>
+<TYPE>gboolean</TYPE>
+<RANGE></RANGE>
+<FLAGS>rwx</FLAGS>
+<NICK>Streamable</NICK>
+<BLURB>If set to true, the output should be as if it is to be streamed and hence no indexes written or duration written.</BLURB>
+<DEFAULT>FALSE</DEFAULT>
+</ARG>
+
+<ARG>
+<NAME>GstQTMux::trak-timescale</NAME>
+<TYPE>guint</TYPE>
+<RANGE></RANGE>
+<FLAGS>rwx</FLAGS>
+<NICK>Track timescale</NICK>
+<BLURB>Timescale to use for the tracks (units per second, 0 is automatic).</BLURB>
+<DEFAULT>0</DEFAULT>
+</ARG>
+
+<ARG>
+<NAME>GstQTMoovRecover::broken-input</NAME>
+<TYPE>gchar*</TYPE>
+<RANGE></RANGE>
+<FLAGS>rw</FLAGS>
+<NICK>Path to broken input file</NICK>
+<BLURB>Path to broken input file. (If qtmux was on faststart mode, this file is the faststart file).</BLURB>
+<DEFAULT>NULL</DEFAULT>
+</ARG>
+
+<ARG>
+<NAME>GstQTMoovRecover::faststart-mode</NAME>
+<TYPE>gboolean</TYPE>
+<RANGE></RANGE>
+<FLAGS>rw</FLAGS>
+<NICK>If the broken input is from faststart mode</NICK>
+<BLURB>If the broken input is from faststart mode.</BLURB>
+<DEFAULT>FALSE</DEFAULT>
+</ARG>
+
+<ARG>
+<NAME>GstQTMoovRecover::fixed-output</NAME>
+<TYPE>gchar*</TYPE>
+<RANGE></RANGE>
+<FLAGS>rw</FLAGS>
+<NICK>Path to write the fixed file</NICK>
+<BLURB>Path to write the fixed file to (used as output).</BLURB>
+<DEFAULT>NULL</DEFAULT>
+</ARG>
+
+<ARG>
+<NAME>GstQTMoovRecover::recovery-input</NAME>
+<TYPE>gchar*</TYPE>
+<RANGE></RANGE>
+<FLAGS>rw</FLAGS>
+<NICK>Path to recovery file</NICK>
+<BLURB>Path to recovery file (used as input).</BLURB>
+<DEFAULT>NULL</DEFAULT>
+</ARG>
+
+<ARG>
+<NAME>GstMP4Mux::dts-method</NAME>
+<TYPE>GstQTMuxDtsMethods</TYPE>
+<RANGE></RANGE>
+<FLAGS>rwx</FLAGS>
+<NICK>dts-method</NICK>
+<BLURB>Method to determine DTS time.</BLURB>
+<DEFAULT>reorder</DEFAULT>
+</ARG>
+
+<ARG>
+<NAME>GstMP4Mux::faststart</NAME>
+<TYPE>gboolean</TYPE>
+<RANGE></RANGE>
+<FLAGS>rw</FLAGS>
+<NICK>Format file to faststart</NICK>
+<BLURB>If the file should be formatted for faststart (headers first).</BLURB>
+<DEFAULT>FALSE</DEFAULT>
+</ARG>
+
+<ARG>
+<NAME>GstMP4Mux::faststart-file</NAME>
+<TYPE>gchar*</TYPE>
+<RANGE></RANGE>
+<FLAGS>rwx</FLAGS>
+<NICK>File to use for storing buffers</NICK>
+<BLURB>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.</BLURB>
+<DEFAULT>NULL</DEFAULT>
+</ARG>
+
+<ARG>
+<NAME>GstMP4Mux::fragment-duration</NAME>
+<TYPE>guint</TYPE>
+<RANGE></RANGE>
+<FLAGS>rwx</FLAGS>
+<NICK>Fragment duration</NICK>
+<BLURB>Fragment durations in ms (produce a fragmented file if > 0).</BLURB>
+<DEFAULT>0</DEFAULT>
+</ARG>
+
+<ARG>
+<NAME>GstMP4Mux::moov-recovery-file</NAME>
+<TYPE>gchar*</TYPE>
+<RANGE></RANGE>
+<FLAGS>rwx</FLAGS>
+<NICK>File to store data for posterior moov atom recovery</NICK>
+<BLURB>File to be used to store data for moov atom making movie file recovery possible in case of a crash during muxing. Null for disabled. (Experimental).</BLURB>
+<DEFAULT>NULL</DEFAULT>
+</ARG>
+
+<ARG>
+<NAME>GstMP4Mux::movie-timescale</NAME>
+<TYPE>guint</TYPE>
+<RANGE>>= 1</RANGE>
+<FLAGS>rwx</FLAGS>
+<NICK>Movie timescale</NICK>
+<BLURB>Timescale to use in the movie (units per second).</BLURB>
+<DEFAULT>1000</DEFAULT>
+</ARG>
+
+<ARG>
+<NAME>GstMP4Mux::presentation-time</NAME>
+<TYPE>gboolean</TYPE>
+<RANGE></RANGE>
+<FLAGS>rwx</FLAGS>
+<NICK>Include presentation-time info</NICK>
+<BLURB>Calculate and include presentation/composition time (in addition to decoding time).</BLURB>
+<DEFAULT>TRUE</DEFAULT>
+</ARG>
+
+<ARG>
+<NAME>GstMP4Mux::streamable</NAME>
+<TYPE>gboolean</TYPE>
+<RANGE></RANGE>
+<FLAGS>rwx</FLAGS>
+<NICK>Streamable</NICK>
+<BLURB>If set to true, the output should be as if it is to be streamed and hence no indexes written or duration written.</BLURB>
+<DEFAULT>FALSE</DEFAULT>
+</ARG>
+
+<ARG>
+<NAME>GstMP4Mux::trak-timescale</NAME>
+<TYPE>guint</TYPE>
+<RANGE></RANGE>
+<FLAGS>rwx</FLAGS>
+<NICK>Track timescale</NICK>
+<BLURB>Timescale to use for the tracks (units per second, 0 is automatic).</BLURB>
+<DEFAULT>0</DEFAULT>
+</ARG>
+
+<ARG>
+<NAME>GstMJ2Mux::dts-method</NAME>
+<TYPE>GstQTMuxDtsMethods</TYPE>
+<RANGE></RANGE>
+<FLAGS>rwx</FLAGS>
+<NICK>dts-method</NICK>
+<BLURB>Method to determine DTS time.</BLURB>
+<DEFAULT>reorder</DEFAULT>
+</ARG>
+
+<ARG>
+<NAME>GstMJ2Mux::faststart</NAME>
+<TYPE>gboolean</TYPE>
+<RANGE></RANGE>
+<FLAGS>rw</FLAGS>
+<NICK>Format file to faststart</NICK>
+<BLURB>If the file should be formatted for faststart (headers first).</BLURB>
+<DEFAULT>FALSE</DEFAULT>
+</ARG>
+
+<ARG>
+<NAME>GstMJ2Mux::faststart-file</NAME>
+<TYPE>gchar*</TYPE>
+<RANGE></RANGE>
+<FLAGS>rwx</FLAGS>
+<NICK>File to use for storing buffers</NICK>
+<BLURB>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.</BLURB>
+<DEFAULT>NULL</DEFAULT>
+</ARG>
+
+<ARG>
+<NAME>GstMJ2Mux::fragment-duration</NAME>
+<TYPE>guint</TYPE>
+<RANGE></RANGE>
+<FLAGS>rwx</FLAGS>
+<NICK>Fragment duration</NICK>
+<BLURB>Fragment durations in ms (produce a fragmented file if > 0).</BLURB>
+<DEFAULT>0</DEFAULT>
+</ARG>
+
+<ARG>
+<NAME>GstMJ2Mux::moov-recovery-file</NAME>
+<TYPE>gchar*</TYPE>
+<RANGE></RANGE>
+<FLAGS>rwx</FLAGS>
+<NICK>File to store data for posterior moov atom recovery</NICK>
+<BLURB>File to be used to store data for moov atom making movie file recovery possible in case of a crash during muxing. Null for disabled. (Experimental).</BLURB>
+<DEFAULT>NULL</DEFAULT>
+</ARG>
+
+<ARG>
+<NAME>GstMJ2Mux::movie-timescale</NAME>
+<TYPE>guint</TYPE>
+<RANGE>>= 1</RANGE>
+<FLAGS>rwx</FLAGS>
+<NICK>Movie timescale</NICK>
+<BLURB>Timescale to use in the movie (units per second).</BLURB>
+<DEFAULT>1000</DEFAULT>
+</ARG>
+
+<ARG>
+<NAME>GstMJ2Mux::presentation-time</NAME>
+<TYPE>gboolean</TYPE>
+<RANGE></RANGE>
+<FLAGS>rwx</FLAGS>
+<NICK>Include presentation-time info</NICK>
+<BLURB>Calculate and include presentation/composition time (in addition to decoding time).</BLURB>
+<DEFAULT>TRUE</DEFAULT>
+</ARG>
+
+<ARG>
+<NAME>GstMJ2Mux::streamable</NAME>
+<TYPE>gboolean</TYPE>
+<RANGE></RANGE>
+<FLAGS>rwx</FLAGS>
+<NICK>Streamable</NICK>
+<BLURB>If set to true, the output should be as if it is to be streamed and hence no indexes written or duration written.</BLURB>
+<DEFAULT>FALSE</DEFAULT>
+</ARG>
+
+<ARG>
+<NAME>GstMJ2Mux::trak-timescale</NAME>
+<TYPE>guint</TYPE>
+<RANGE></RANGE>
+<FLAGS>rwx</FLAGS>
+<NICK>Track timescale</NICK>
+<BLURB>Timescale to use for the tracks (units per second, 0 is automatic).</BLURB>
+<DEFAULT>0</DEFAULT>
+</ARG>
+
+<ARG>
+<NAME>GstISMLMux::dts-method</NAME>
+<TYPE>GstQTMuxDtsMethods</TYPE>
+<RANGE></RANGE>
+<FLAGS>rwx</FLAGS>
+<NICK>dts-method</NICK>
+<BLURB>Method to determine DTS time.</BLURB>
+<DEFAULT>reorder</DEFAULT>
+</ARG>
+
+<ARG>
+<NAME>GstISMLMux::faststart</NAME>
+<TYPE>gboolean</TYPE>
+<RANGE></RANGE>
+<FLAGS>rw</FLAGS>
+<NICK>Format file to faststart</NICK>
+<BLURB>If the file should be formatted for faststart (headers first).</BLURB>
+<DEFAULT>FALSE</DEFAULT>
+</ARG>
+
+<ARG>
+<NAME>GstISMLMux::faststart-file</NAME>
+<TYPE>gchar*</TYPE>
+<RANGE></RANGE>
+<FLAGS>rwx</FLAGS>
+<NICK>File to use for storing buffers</NICK>
+<BLURB>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.</BLURB>
+<DEFAULT>NULL</DEFAULT>
+</ARG>
+
+<ARG>
+<NAME>GstISMLMux::fragment-duration</NAME>
+<TYPE>guint</TYPE>
+<RANGE></RANGE>
+<FLAGS>rwx</FLAGS>
+<NICK>Fragment duration</NICK>
+<BLURB>Fragment durations in ms (produce a fragmented file if > 0).</BLURB>
+<DEFAULT>2000</DEFAULT>
+</ARG>
+
+<ARG>
+<NAME>GstISMLMux::moov-recovery-file</NAME>
+<TYPE>gchar*</TYPE>
+<RANGE></RANGE>
+<FLAGS>rwx</FLAGS>
+<NICK>File to store data for posterior moov atom recovery</NICK>
+<BLURB>File to be used to store data for moov atom making movie file recovery possible in case of a crash during muxing. Null for disabled. (Experimental).</BLURB>
+<DEFAULT>NULL</DEFAULT>
+</ARG>
+
+<ARG>
+<NAME>GstISMLMux::movie-timescale</NAME>
+<TYPE>guint</TYPE>
+<RANGE>>= 1</RANGE>
+<FLAGS>rwx</FLAGS>
+<NICK>Movie timescale</NICK>
+<BLURB>Timescale to use in the movie (units per second).</BLURB>
+<DEFAULT>1000</DEFAULT>
+</ARG>
+
+<ARG>
+<NAME>GstISMLMux::presentation-time</NAME>
+<TYPE>gboolean</TYPE>
+<RANGE></RANGE>
+<FLAGS>rwx</FLAGS>
+<NICK>Include presentation-time info</NICK>
+<BLURB>Calculate and include presentation/composition time (in addition to decoding time).</BLURB>
+<DEFAULT>TRUE</DEFAULT>
+</ARG>
+
+<ARG>
+<NAME>GstISMLMux::streamable</NAME>
+<TYPE>gboolean</TYPE>
+<RANGE></RANGE>
+<FLAGS>rwx</FLAGS>
+<NICK>Streamable</NICK>
+<BLURB>If set to true, the output should be as if it is to be streamed and hence no indexes written or duration written.</BLURB>
+<DEFAULT>FALSE</DEFAULT>
+</ARG>
+
+<ARG>
+<NAME>GstISMLMux::trak-timescale</NAME>
+<TYPE>guint</TYPE>
+<RANGE></RANGE>
+<FLAGS>rwx</FLAGS>
+<NICK>Track timescale</NICK>
+<BLURB>Timescale to use for the tracks (units per second, 0 is automatic).</BLURB>
+<DEFAULT>0</DEFAULT>
+</ARG>
+
+<ARG>
+<NAME>GstGPPMux::dts-method</NAME>
+<TYPE>GstQTMuxDtsMethods</TYPE>
+<RANGE></RANGE>
+<FLAGS>rwx</FLAGS>
+<NICK>dts-method</NICK>
+<BLURB>Method to determine DTS time.</BLURB>
+<DEFAULT>reorder</DEFAULT>
+</ARG>
+
+<ARG>
+<NAME>GstGPPMux::faststart</NAME>
+<TYPE>gboolean</TYPE>
+<RANGE></RANGE>
+<FLAGS>rw</FLAGS>
+<NICK>Format file to faststart</NICK>
+<BLURB>If the file should be formatted for faststart (headers first).</BLURB>
+<DEFAULT>FALSE</DEFAULT>
+</ARG>
+
+<ARG>
+<NAME>GstGPPMux::faststart-file</NAME>
+<TYPE>gchar*</TYPE>
+<RANGE></RANGE>
+<FLAGS>rwx</FLAGS>
+<NICK>File to use for storing buffers</NICK>
+<BLURB>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.</BLURB>
+<DEFAULT>NULL</DEFAULT>
+</ARG>
+
+<ARG>
+<NAME>GstGPPMux::fragment-duration</NAME>
+<TYPE>guint</TYPE>
+<RANGE></RANGE>
+<FLAGS>rwx</FLAGS>
+<NICK>Fragment duration</NICK>
+<BLURB>Fragment durations in ms (produce a fragmented file if > 0).</BLURB>
+<DEFAULT>0</DEFAULT>
+</ARG>
+
+<ARG>
+<NAME>GstGPPMux::moov-recovery-file</NAME>
+<TYPE>gchar*</TYPE>
+<RANGE></RANGE>
+<FLAGS>rwx</FLAGS>
+<NICK>File to store data for posterior moov atom recovery</NICK>
+<BLURB>File to be used to store data for moov atom making movie file recovery possible in case of a crash during muxing. Null for disabled. (Experimental).</BLURB>
+<DEFAULT>NULL</DEFAULT>
+</ARG>
+
+<ARG>
+<NAME>GstGPPMux::movie-timescale</NAME>
+<TYPE>guint</TYPE>
+<RANGE>>= 1</RANGE>
+<FLAGS>rwx</FLAGS>
+<NICK>Movie timescale</NICK>
+<BLURB>Timescale to use in the movie (units per second).</BLURB>
+<DEFAULT>1000</DEFAULT>
+</ARG>
+
+<ARG>
+<NAME>GstGPPMux::presentation-time</NAME>
+<TYPE>gboolean</TYPE>
+<RANGE></RANGE>
+<FLAGS>rwx</FLAGS>
+<NICK>Include presentation-time info</NICK>
+<BLURB>Calculate and include presentation/composition time (in addition to decoding time).</BLURB>
+<DEFAULT>TRUE</DEFAULT>
+</ARG>
+
+<ARG>
+<NAME>GstGPPMux::streamable</NAME>
+<TYPE>gboolean</TYPE>
+<RANGE></RANGE>
+<FLAGS>rwx</FLAGS>
+<NICK>Streamable</NICK>
+<BLURB>If set to true, the output should be as if it is to be streamed and hence no indexes written or duration written.</BLURB>
+<DEFAULT>FALSE</DEFAULT>
+</ARG>
+
+<ARG>
+<NAME>GstGPPMux::trak-timescale</NAME>
+<TYPE>guint</TYPE>
+<RANGE></RANGE>
+<FLAGS>rwx</FLAGS>
+<NICK>Track timescale</NICK>
+<BLURB>Timescale to use for the tracks (units per second, 0 is automatic).</BLURB>
+<DEFAULT>0</DEFAULT>
+</ARG>
+
diff --git a/docs/plugins/gst-plugins-good-plugins.hierarchy b/docs/plugins/gst-plugins-good-plugins.hierarchy
index b8e1a8261..b8db7c3fa 100644
--- a/docs/plugins/gst-plugins-good-plugins.hierarchy
+++ b/docs/plugins/gst-plugins-good-plugins.hierarchy
@@ -1,302 +1,317 @@
GObject
- GdkPixbuf
- GstCmmlTagClip
- GstCmmlTagHead
- GstCmmlTagStream
- GstColorBalanceChannel
GstObject
- GstBus
- GstClock
- GstSystemClock
- GstAudioClock
+ GstPad
+ GstVideoMixer2Pad
+ GstVideoMixerPad
+ GstInterleavePad
+ GstPadTemplate
+ GstPluginFeature
+ GstElementFactory
+ GstTypeFindFactory
+ GstIndexFactory
GstElement
- GstALawDec
- GstALawEnc
- GstAsteriskh263
- GstAuParse
- GstAviDemux
- GstAviMux
- GstAviSubtitle
+ GstBin
+ GstPipeline
+ GstQTMoovRecover
+ GstSwitchSink
+ GstGConfVideoSink
+ GstGConfAudioSink
+ GstSwitchSrc
+ GstGConfVideoSrc
+ GstGConfAudioSrc
+ GstHalAudioSink
+ GstHalAudioSrc
+ GstRtpBin
+ GstAutoVideoSink
+ GstAutoVideoSrc
+ GstAutoAudioSink
+ GstAutoAudioSrc
+ GstPushFileSrc
+ GstRTSPSrc
+ GstRgVolume
+ GstAspectRatioCrop
+ GstBaseSink
+ GstBaseAudioSink
+ GstPulseSink
+ GstJackAudioSink
+ GstAudioSink
+ GstEsdSink
+ GstOssSink
+ GstOss4Sink
+ GstVideoSink
+ GstV4l2Sink
+ GstGdkPixbufSink
+ GstAASink
+ GstCACASink
+ GstShout2send
+ GstTest
+ GstMultiFileSink
+ GstMultiUDPSink
+ GstUDPSink
+ GstDynUDPSink
+ GstBaseSrc
+ GstPushSrc
+ GstBaseAudioSrc
+ GstAudioSrc
+ GstPulseSrc
+ GstOssSrc
+ GstOss4Source
+ GstJackAudioSrc
+ GstV4l2Src
+ GstDV1394Src
+ GstHDV1394Src
+ GstSoupHTTPSrc
+ GstXImageSrc
+ GstMultiFileSrc
+ GstUDPSrc
+ GstPulseMixer
+ GstSpeexEnc
+ GstSpeexDec
+ GstV4l2Radio
+ GstRTPDepay
GstBaseRTPDepayload
+ GstRtpAC3Depay
GstRTPBVDepay
+ GstRtpCELTDepay
GstRTPDVDepay
- GstRTPGSMDepay
- GstRTPSirenDepay
+ GstRtpGSTDepay
GstRTPiLBCDepay
- GstRtpAC3Depay
- GstRtpAMRDepay
- GstRtpCELTDepay
GstRtpG722Depay
GstRtpG723Depay
GstRtpG726Depay
GstRtpG729Depay
- GstRtpGSTDepay
- GstRtpH263Depay
+ GstRTPGSMDepay
+ GstRtpAMRDepay
+ GstRtpPcmaDepay
+ GstRtpPcmuDepay
+ GstRtpMPADepay
+ GstRtpMPARobustDepay
+ GstRtpMPVDepay
GstRtpH263PDepay
+ GstRtpH263Depay
GstRtpH264Depay
GstRtpJ2KDepay
GstRtpJPEGDepay
GstRtpL16Depay
GstRtpMP1SDepay
GstRtpMP2TDepay
+ GstRtpMP4VDepay
GstRtpMP4ADepay
GstRtpMP4GDepay
- GstRtpMP4VDepay
- GstRtpMPADepay
- GstRtpMPARobustDepay
- GstRtpMPVDepay
- GstRtpPcmaDepay
- GstRtpPcmuDepay
GstRtpQCELPDepay
GstRtpQDM2Depay
+ GstRTPSirenDepay
GstRtpSPEEXDepay
GstRtpSV3VDepay
GstRtpTheoraDepay
- GstRtpVRawDepay
GstRtpVorbisDepay
+ GstRtpVRawDepay
GstRtpXQTDepay
GstBaseRTPPayload
+ GstRtpAC3Pay
GstBaseRTPAudioPayload
GstRTPBVPay
GstRTPILBCPay
- GstRTPSirenPay
GstRtpG722Pay
GstRtpG726Pay
- GstRtpL16Pay
- GstRtpPcmaPay
GstRtpPcmuPay
+ GstRtpPcmaPay
+ GstRtpL16Pay
+ GstRTPSirenPay
+ GstRtpCELTPay
GstRTPDVPay
+ GstRtpGSTPay
GstRTPG723Pay
GstRTPG729Pay
GstRTPGSMPay
- GstRTPMP2TPay
- GstRTPMPVPay
- GstRtpAC3Pay
GstRtpAMRPay
- GstRtpCELTPay
- GstRtpGSTPay
+ GstRtpMPAPay
+ GstRTPMPVPay
GstRtpH263PPay
GstRtpH263Pay
GstRtpH264Pay
GstRtpJ2KPay
GstRtpJPEGPay
+ GstRTPMP2TPay
+ GstRtpMP4VPay
GstRtpMP4APay
GstRtpMP4GPay
- GstRtpMP4VPay
- GstRtpMPAPay
GstRtpSPEEXPay
GstRtpTheoraPay
- GstRtpVRawPay
GstRtpVorbisPay
- GstBaseSink
- GstAASink
- GstBaseAudioSink
- GstAudioSink
- GstEsdSink
- GstOss4Sink
- GstOssSink
- GstJackAudioSink
- GstPulseSink
- GstCACASink
- GstDynUDPSink
- GstMultiFileSink
- GstMultiUDPSink
- GstUDPSink
- GstShout2send
- GstTest
- GstVideoSink
- GstGdkPixbufSink
- GstV4l2Sink
- GstBaseSrc
- GstPushSrc
- GstBaseAudioSrc
- GstAudioSrc
- GstOss4Source
- GstOssSrc
- GstPulseSrc
- GstJackAudioSrc
- GstDV1394Src
- GstHDV1394Src
- GstMultiFileSrc
- GstSoupHTTPSrc
- GstUDPSrc
- GstV4l2Src
- GstXImageSrc
+ GstRtpVRawPay
+ GstAsteriskh263
+ GstMatroskaDemux
+ GstMatroskaParse
+ GstMatroskaMux
+ GstWebMMux
+ GstDeinterlace
+ GstCmmlEnc
+ GstCmmlDec
+ GstWavpackParse
+ GstWavpackDec
+ GstWavpackEnc
+ GstDVDemux
+ GstDVDec
+ GstFlacEnc
+ GstFlacDec
+ GstFlacTag
+ GstCairoTextOverlay
GstBaseTransform
- GstAudioFilter
- GstAudioAmplify
- GstAudioDynamic
- GstAudioEcho
- GstAudioFXBaseFIRFilter
- GstAudioFIRFilter
- GstAudioWSincBand
- GstAudioWSincLimit
- GstAudioFXBaseIIRFilter
- GstAudioChebBand
- GstAudioChebLimit
- GstAudioIIRFilter
- GstAudioInvert
- GstAudioKaraoke
- GstIirEqualizer
- GstIirEqualizer10Bands
- GstIirEqualizer3Bands
- GstIirEqualizerNBands
- GstSpectrum
- GstAudioPanorama
- GstBreakMyData
GstCairoTimeOverlay
- GstCapsSetter
- GstCpuReport
- GstLevel
- GstNavSeek
- GstPixbufScale
- GstProgressReport
- GstRgAnalysis
- GstRgLimiter
- GstTagInject
- GstVideoBox
- GstVideoCrop
GstVideoFilter
- GstAgingTV
- GstAlpha
- GstAlphaColor
GstCairoOverlay
- GstDiceTV
GstEdgeTV
- GstGamma
- GstNavigationtest
- GstOpTV
+ GstAgingTV
+ GstDiceTV
+ GstWarpTV
+ GstShagadelicTV
+ GstVertigoTV
+ GstRevTV
GstQuarkTV
+ GstOpTV
GstRadioacTV
- GstRevTV
- GstRippleTV
- GstSMPTEAlpha
- GstShagadelicTV
GstStreakTV
- GstVertigoTV
+ GstRippleTV
+ GstNavigationtest
+ GstGamma
GstVideoBalance
GstVideoFlip
- GstWarpTV
- GstBin
- GstAspectRatioCrop
- GstAutoAudioSink
- GstAutoAudioSrc
- GstAutoVideoSink
- GstAutoVideoSrc
- GstHalAudioSink
- GstHalAudioSrc
- GstPipeline
- GstPushFileSrc
- GstRTSPSrc
- GstRgVolume
- GstRtpBin
- GstSwitchSink
- GstGConfAudioSink
- GstGConfVideoSink
- GstSwitchSrc
- GstGConfAudioSrc
- GstGConfVideoSrc
+ GstSMPTEAlpha
+ GstAlpha
+ GstAlphaColor
+ GstPixbufScale
+ GstVideoBox
+ GstBreakMyData
+ GstCapsSetter
+ GstNavSeek
+ GstProgressReport
+ GstTagInject
+ GstCpuReport
+ GstLevel
+ GstAudioFilter
+ GstIirEqualizer
+ GstIirEqualizerNBands
+ GstIirEqualizer3Bands
+ GstIirEqualizer10Bands
+ GstSpectrum
+ GstAudioInvert
+ GstAudioKaraoke
+ GstAudioAmplify
+ GstAudioDynamic
+ GstAudioFXBaseIIRFilter
+ GstAudioChebLimit
+ GstAudioChebBand
+ GstAudioIIRFilter
+ GstAudioFXBaseFIRFilter
+ GstAudioWSincLimit
+ GstAudioWSincBand
+ GstAudioFIRFilter
+ GstAudioEcho
+ GstRgAnalysis
+ GstRgLimiter
+ GstVideoCrop
+ GstAudioPanorama
GstCairoRender
- GstCairoTextOverlay
- GstCapsDebug
- GstCmmlDec
- GstCmmlEnc
- GstCutter
- GstDVDec
- GstDVDemux
- GstDeinterlace
- GstDeinterleave
- GstEFence
- GstFlacDec
- GstFlacEnc
- GstFlacTag
- GstFlvDemux
- GstFlvMux
- GstFlxDec
- GstGdkPixbuf
- GstGoom
- GstGoom2k1
- GstICYDemux
- GstImageFreeze
- GstInterleave
- GstJpegDec
GstJpegEnc
- GstMatroskaDemux
- GstMatroskaMux
- GstWebMMux
- GstMonoscope
- GstMuLawDec
- GstMuLawEnc
- GstMultipartDemux
- GstMultipartMux
- GstOss4Mixer
- GstOssMixerElement
+ GstJpegDec
+ GstSmokeEnc
+ GstSmokeDec
GstPngDec
GstPngEnc
- GstPulseMixer
- GstQTDemux
- GstRTPDec
- GstRTPDepay
- GstRndBufferSize
+ GstGdkPixbuf
+ GstOssMixerElement
+ GstOss4Mixer
+ GstShapeWipe
+ GstAviDemux
+ GstAviMux
+ GstAviSubtitle
+ GstGoom
+ GstGoom2k1
+ GstWavEnc
GstRtpJitterBuffer
GstRtpPtDemux
GstRtpSession
GstRtpSsrcDemux
+ GstQTDemux
+ GstQTMux
+ GstMP4Mux
+ GstISMLMux
+ GstGPPMux
+ GstMJ2Mux
+ GstRndBufferSize
+ GstCapsDebug
+ GstEFence
+ GstCutter
+ GstRTPDec
GstSMPTE
- GstShapeWipe
- GstSmokeDec
- GstSmokeEnc
- GstSpeexDec
- GstSpeexEnc
+ GstAuParse
+ GstMultipartDemux
+ GstMultipartMux
+ GstALawEnc
+ GstALawDec
+ GstMuLawEnc
+ GstMuLawDec
GstTagDemux
GstApeDemux
GstID3Demux
- GstTagLibMux
- GstApev2Mux
- GstId3v2Mux
+ GstFlxDec
+ GstImageFreeze
+ GstBaseParse
+ GstAacParse
+ GstAmrParse
+ GstAc3Parse
+ GstDcaParse
+ GstFlacParse
+ GstMpegAudioParse
+ GstY4mEncode
+ GstInterleave
+ GstDeinterleave
+ GstWavParse
+ GstFlvDemux
+ GstFlvMux
+ GstMonoscope
+ GstICYDemux
GstVideoMixer
GstVideoMixer2
- GstWavEnc
- GstWavParse
- GstWavpackDec
- GstWavpackEnc
- GstWavpackParse
- GstY4mEncode
- GstPad
- GstInterleavePad
- GstVideoMixer2Pad
- GstVideoMixerPad
- GstPadTemplate
+ GstBus
+ GstTask
+ GstTaskPool
+ GstClock
+ GstSystemClock
+ GstAudioClock
GstPlugin
- GstPluginFeature
- GstElementFactory
- GstIndexFactory
- GstTypeFindFactory
GstRegistry
GstRingBuffer
- GstAudioSinkRingBuffer
GstAudioSrcRingBuffer
- GstJackAudioSinkRingBuffer
+ GstAudioSinkRingBuffer
GstJackAudioSrcRingBuffer
- GstTask
- GstTaskPool
+ GstJackAudioSinkRingBuffer
GstSignalObject
- GstTunerChannel
- GstTunerNorm
+ GstCmmlTagStream
+ GstCmmlTagHead
+ GstCmmlTagClip
+ GstColorBalanceChannel
RTPSession
+ GstMixerTrack
+ GstMixerOptions
+ GdkPixbuf
+ GstTunerNorm
+ GstTunerChannel
GInterface
- GIcon
GTypePlugin
GstChildProxy
- GstColorBalance
+ GstURIHandler
+ GstStreamVolume
GstImplementsInterface
- GstMixer
- GstNavigation
- GstPreset
GstPropertyProbe
- GstStreamVolume
+ GstMixer
GstTagSetter
+ GstPreset
GstTuner
- GstURIHandler
+ GstColorBalance
GstVideoOrientation
GstXOverlay
+ GstNavigation
+ GstTagXmpWriter
+ GIcon
diff --git a/docs/plugins/gst-plugins-good-plugins.interfaces b/docs/plugins/gst-plugins-good-plugins.interfaces
index 1d66c50f5..631b07915 100644
--- a/docs/plugins/gst-plugins-good-plugins.interfaces
+++ b/docs/plugins/gst-plugins-good-plugins.interfaces
@@ -1,55 +1,59 @@
GstBin GstChildProxy
GstPipeline GstChildProxy
-GstHalAudioSink GstChildProxy
-GstHalAudioSrc GstChildProxy
+GstQTMoovRecover GstChildProxy
GstSwitchSink GstChildProxy
GstGConfVideoSink GstChildProxy
GstGConfAudioSink GstChildProxy
GstSwitchSrc GstChildProxy
GstGConfVideoSrc GstChildProxy
GstGConfAudioSrc GstChildProxy
-GstRTSPSrc GstChildProxy GstURIHandler
+GstHalAudioSink GstChildProxy
+GstHalAudioSrc GstChildProxy
GstRtpBin GstChildProxy
-GstPushFileSrc GstChildProxy GstURIHandler
GstAutoVideoSink GstChildProxy
GstAutoVideoSrc GstChildProxy
GstAutoAudioSink GstChildProxy
GstAutoAudioSrc GstChildProxy
+GstPushFileSrc GstChildProxy GstURIHandler
+GstRTSPSrc GstChildProxy GstURIHandler
GstRgVolume GstChildProxy
GstAspectRatioCrop GstChildProxy
-GstVideoBalance GstImplementsInterface GstColorBalance
-GstIirEqualizer GstChildProxy
-GstIirEqualizerNBands GstChildProxy
-GstIirEqualizer3Bands GstChildProxy GstPreset
-GstIirEqualizer10Bands GstChildProxy GstPreset
-GstSoupHTTPSrc GstURIHandler
-GstPulseSrc GstImplementsInterface GstMixer GstPropertyProbe
-GstOss4Source GstImplementsInterface GstMixer GstPropertyProbe
-GstOssSrc GstImplementsInterface GstMixer
-GstDV1394Src GstURIHandler GstPropertyProbe
-GstHDV1394Src GstURIHandler GstPropertyProbe
-GstV4l2Src GstURIHandler GstImplementsInterface GstTuner GstColorBalance GstVideoOrientation GstPropertyProbe
-GstUDPSrc GstURIHandler
GstPulseSink GstStreamVolume GstImplementsInterface GstPropertyProbe
GstOss4Sink GstStreamVolume GstPropertyProbe
GstV4l2Sink GstImplementsInterface GstXOverlay GstNavigation GstColorBalance GstVideoOrientation GstPropertyProbe
GstShout2send GstTagSetter
GstUDPSink GstURIHandler
+GstPulseSrc GstImplementsInterface GstMixer GstPropertyProbe
+GstOssSrc GstImplementsInterface GstMixer
+GstOss4Source GstImplementsInterface GstMixer GstPropertyProbe
+GstV4l2Src GstURIHandler GstImplementsInterface GstTuner GstColorBalance GstVideoOrientation GstPropertyProbe
+GstDV1394Src GstURIHandler GstPropertyProbe
+GstHDV1394Src GstURIHandler GstPropertyProbe
+GstSoupHTTPSrc GstURIHandler
+GstUDPSrc GstURIHandler
GstPulseMixer GstImplementsInterface GstMixer GstPropertyProbe
-GstTagLibMux GstTagSetter
-GstId3v2Mux GstTagSetter
-GstApev2Mux GstTagSetter
-GstFlacEnc GstTagSetter GstPreset
-GstFlacTag GstTagSetter
-GstWavpackEnc GstPreset
GstSpeexEnc GstTagSetter GstPreset
-GstOss4Mixer GstImplementsInterface GstMixer GstPropertyProbe
-GstOssMixerElement GstImplementsInterface GstMixer
+GstV4l2Radio GstURIHandler GstImplementsInterface GstTuner GstPropertyProbe
GstMatroskaMux GstTagSetter
GstWebMMux GstTagSetter
+GstDeinterlace GstChildProxy
+GstWavpackEnc GstPreset
+GstFlacEnc GstTagSetter GstPreset
+GstFlacTag GstTagSetter
+GstVideoBalance GstImplementsInterface GstColorBalance
+GstIirEqualizer GstChildProxy
+GstIirEqualizerNBands GstChildProxy
+GstIirEqualizer3Bands GstChildProxy GstPreset
+GstIirEqualizer10Bands GstChildProxy GstPreset
+GstOssMixerElement GstImplementsInterface GstMixer
+GstOss4Mixer GstImplementsInterface GstMixer GstPropertyProbe
+GstAviMux GstTagSetter
+GstQTMux GstTagSetter GstTagXmpWriter
+GstMP4Mux GstTagSetter GstTagXmpWriter
+GstISMLMux GstTagSetter GstTagXmpWriter
+GstGPPMux GstTagSetter GstTagXmpWriter
+GstMJ2Mux GstTagSetter GstTagXmpWriter
+GstFlvMux GstTagSetter
GstVideoMixer GstChildProxy
GstVideoMixer2 GstChildProxy
-GstFlvMux GstTagSetter
-GstAviMux GstTagSetter
-GstDeinterlace GstChildProxy
GdkPixbuf GIcon
diff --git a/docs/plugins/gst-plugins-good-plugins.prerequisites b/docs/plugins/gst-plugins-good-plugins.prerequisites
index 743a46ffb..f64bf0f3c 100644
--- a/docs/plugins/gst-plugins-good-plugins.prerequisites
+++ b/docs/plugins/gst-plugins-good-plugins.prerequisites
@@ -7,4 +7,5 @@ GstTuner GstImplementsInterface GstElement
GstColorBalance GstImplementsInterface GstElement
GstVideoOrientation GstImplementsInterface GstElement
GstXOverlay GstImplementsInterface GstElement
+GstTagXmpWriter GstElement
GIcon GObject
diff --git a/docs/plugins/inspect/plugin-1394.xml b/docs/plugins/inspect/plugin-1394.xml
index 626f7c71e..5aa3c3e88 100644
--- a/docs/plugins/inspect/plugin-1394.xml
+++ b/docs/plugins/inspect/plugin-1394.xml
@@ -3,10 +3,10 @@
<description>Source for video data via IEEE1394 interface</description>
<filename>../../ext/raw1394/.libs/libgst1394.so</filename>
<basename>libgst1394.so</basename>
- <version>0.10.28.1</version>
+ <version>0.10.28.2</version>
<license>LGPL</license>
<source>gst-plugins-good</source>
- <package>GStreamer Good Plug-ins git</package>
+ <package>GStreamer Good Plug-ins prerelease</package>
<origin>Unknown package origin</origin>
<elements>
<element>
diff --git a/docs/plugins/inspect/plugin-aasink.xml b/docs/plugins/inspect/plugin-aasink.xml
index e1efd97f6..2c3e805e6 100644
--- a/docs/plugins/inspect/plugin-aasink.xml
+++ b/docs/plugins/inspect/plugin-aasink.xml
@@ -3,10 +3,10 @@
<description>ASCII Art video sink</description>
<filename>../../ext/aalib/.libs/libgstaasink.so</filename>
<basename>libgstaasink.so</basename>
- <version>0.10.28.1</version>
+ <version>0.10.28.2</version>
<license>LGPL</license>
<source>gst-plugins-good</source>
- <package>GStreamer Good Plug-ins git</package>
+ <package>GStreamer Good Plug-ins prerelease</package>
<origin>Unknown package origin</origin>
<elements>
<element>
diff --git a/docs/plugins/inspect/plugin-alaw.xml b/docs/plugins/inspect/plugin-alaw.xml
index 587f10a7d..0f634a9ee 100644
--- a/docs/plugins/inspect/plugin-alaw.xml
+++ b/docs/plugins/inspect/plugin-alaw.xml
@@ -3,10 +3,10 @@
<description>ALaw audio conversion routines</description>
<filename>../../gst/law/.libs/libgstalaw.so</filename>
<basename>libgstalaw.so</basename>
- <version>0.10.28.1</version>
+ <version>0.10.28.2</version>
<license>LGPL</license>
<source>gst-plugins-good</source>
- <package>GStreamer Good Plug-ins git</package>
+ <package>GStreamer Good Plug-ins prerelease</package>
<origin>Unknown package origin</origin>
<elements>
<element>
diff --git a/docs/plugins/inspect/plugin-alpha.xml b/docs/plugins/inspect/plugin-alpha.xml
index 2922c2c70..51308f7e8 100644
--- a/docs/plugins/inspect/plugin-alpha.xml
+++ b/docs/plugins/inspect/plugin-alpha.xml
@@ -3,10 +3,10 @@
<description>adds an alpha channel to video - constant or via chroma-keying</description>
<filename>../../gst/alpha/.libs/libgstalpha.so</filename>
<basename>libgstalpha.so</basename>
- <version>0.10.28.1</version>
+ <version>0.10.28.2</version>
<license>LGPL</license>
<source>gst-plugins-good</source>
- <package>GStreamer Good Plug-ins git</package>
+ <package>GStreamer Good Plug-ins prerelease</package>
<origin>Unknown package origin</origin>
<elements>
<element>
diff --git a/docs/plugins/inspect/plugin-alphacolor.xml b/docs/plugins/inspect/plugin-alphacolor.xml
index 4843e7742..6cbec1713 100644
--- a/docs/plugins/inspect/plugin-alphacolor.xml
+++ b/docs/plugins/inspect/plugin-alphacolor.xml
@@ -3,10 +3,10 @@
<description>RGBA from/to AYUV colorspace conversion preserving the alpha channel</description>
<filename>../../gst/alpha/.libs/libgstalphacolor.so</filename>
<basename>libgstalphacolor.so</basename>
- <version>0.10.28.1</version>
+ <version>0.10.28.2</version>
<license>LGPL</license>
<source>gst-plugins-good</source>
- <package>GStreamer Good Plug-ins git</package>
+ <package>GStreamer Good Plug-ins prerelease</package>
<origin>Unknown package origin</origin>
<elements>
<element>
diff --git a/docs/plugins/inspect/plugin-annodex.xml b/docs/plugins/inspect/plugin-annodex.xml
index e288ffd5b..0f96bc269 100644
--- a/docs/plugins/inspect/plugin-annodex.xml
+++ b/docs/plugins/inspect/plugin-annodex.xml
@@ -3,10 +3,10 @@
<description>annodex stream manipulation (info about annodex: http://www.annodex.net)</description>
<filename>../../ext/annodex/.libs/libgstannodex.so</filename>
<basename>libgstannodex.so</basename>
- <version>0.10.28.1</version>
+ <version>0.10.28.2</version>
<license>LGPL</license>
<source>gst-plugins-good</source>
- <package>GStreamer Good Plug-ins git</package>
+ <package>GStreamer Good Plug-ins prerelease</package>
<origin>Unknown package origin</origin>
<elements>
<element>
diff --git a/docs/plugins/inspect/plugin-apetag.xml b/docs/plugins/inspect/plugin-apetag.xml
index 6a9016a9e..f90487a18 100644
--- a/docs/plugins/inspect/plugin-apetag.xml
+++ b/docs/plugins/inspect/plugin-apetag.xml
@@ -3,10 +3,10 @@
<description>APEv1/2 tag reader</description>
<filename>../../gst/apetag/.libs/libgstapetag.so</filename>
<basename>libgstapetag.so</basename>
- <version>0.10.28.1</version>
+ <version>0.10.28.2</version>
<license>LGPL</license>
<source>gst-plugins-good</source>
- <package>GStreamer Good Plug-ins git</package>
+ <package>GStreamer Good Plug-ins prerelease</package>
<origin>Unknown package origin</origin>
<elements>
<element>
diff --git a/docs/plugins/inspect/plugin-audiofx.xml b/docs/plugins/inspect/plugin-audiofx.xml
index 2e81a18ed..1355c7ac9 100644
--- a/docs/plugins/inspect/plugin-audiofx.xml
+++ b/docs/plugins/inspect/plugin-audiofx.xml
@@ -3,10 +3,10 @@
<description>Audio effects plugin</description>
<filename>../../gst/audiofx/.libs/libgstaudiofx.so</filename>
<basename>libgstaudiofx.so</basename>
- <version>0.10.28.1</version>
+ <version>0.10.28.2</version>
<license>LGPL</license>
<source>gst-plugins-good</source>
- <package>GStreamer Good Plug-ins git</package>
+ <package>GStreamer Good Plug-ins prerelease</package>
<origin>Unknown package origin</origin>
<elements>
<element>
diff --git a/docs/plugins/inspect/plugin-audioparsers.xml b/docs/plugins/inspect/plugin-audioparsers.xml
new file mode 100644
index 000000000..3ecc5c235
--- /dev/null
+++ b/docs/plugins/inspect/plugin-audioparsers.xml
@@ -0,0 +1,139 @@
+<plugin>
+ <name>audioparsers</name>
+ <description>Parsers for various audio formats</description>
+ <filename>../../gst/audioparsers/.libs/libgstaudioparsers.so</filename>
+ <basename>libgstaudioparsers.so</basename>
+ <version>0.10.28.2</version>
+ <license>LGPL</license>
+ <source>gst-plugins-good</source>
+ <package>GStreamer Good Plug-ins prerelease</package>
+ <origin>Unknown package origin</origin>
+ <elements>
+ <element>
+ <name>aacparse</name>
+ <longname>AAC audio stream parser</longname>
+ <class>Codec/Parser/Audio</class>
+ <description>Advanced Audio Coding parser</description>
+ <author>Stefan Kost &lt;stefan.kost@nokia.com&gt;</author>
+ <pads>
+ <caps>
+ <name>sink</name>
+ <direction>sink</direction>
+ <presence>always</presence>
+ <details>audio/mpeg, framed=(boolean)false, mpegversion=(int){ 2, 4 }</details>
+ </caps>
+ <caps>
+ <name>src</name>
+ <direction>source</direction>
+ <presence>always</presence>
+ <details>audio/mpeg, framed=(boolean)true, mpegversion=(int){ 2, 4 }, stream-format=(string){ raw, adts, adif }</details>
+ </caps>
+ </pads>
+ </element>
+ <element>
+ <name>ac3parse</name>
+ <longname>AC3 audio stream parser</longname>
+ <class>Codec/Parser/Audio</class>
+ <description>AC3 parser</description>
+ <author>Tim-Philipp Müller &lt;tim centricular net&gt;</author>
+ <pads>
+ <caps>
+ <name>sink</name>
+ <direction>sink</direction>
+ <presence>always</presence>
+ <details>audio/x-ac3, framed=(boolean)false; audio/x-eac3, framed=(boolean)false; audio/ac3, framed=(boolean)false</details>
+ </caps>
+ <caps>
+ <name>src</name>
+ <direction>source</direction>
+ <presence>always</presence>
+ <details>audio/x-ac3, framed=(boolean)true, channels=(int)[ 1, 6 ], rate=(int)[ 32000, 48000 ]; audio/x-eac3, framed=(boolean)true, channels=(int)[ 1, 6 ], rate=(int)[ 32000, 48000 ]</details>
+ </caps>
+ </pads>
+ </element>
+ <element>
+ <name>amrparse</name>
+ <longname>AMR audio stream parser</longname>
+ <class>Codec/Parser/Audio</class>
+ <description>Adaptive Multi-Rate audio parser</description>
+ <author>Ronald Bultje &lt;rbultje@ronald.bitfreak.net&gt;</author>
+ <pads>
+ <caps>
+ <name>sink</name>
+ <direction>sink</direction>
+ <presence>always</presence>
+ <details>audio/x-amr-nb-sh; audio/x-amr-wb-sh</details>
+ </caps>
+ <caps>
+ <name>src</name>
+ <direction>source</direction>
+ <presence>always</presence>
+ <details>audio/AMR, rate=(int)8000, channels=(int)1; audio/AMR-WB, rate=(int)16000, channels=(int)1</details>
+ </caps>
+ </pads>
+ </element>
+ <element>
+ <name>dcaparse</name>
+ <longname>DTS Coherent Acoustics audio stream parser</longname>
+ <class>Codec/Parser/Audio</class>
+ <description>DCA parser</description>
+ <author>Tim-Philipp Müller &lt;tim centricular net&gt;</author>
+ <pads>
+ <caps>
+ <name>sink</name>
+ <direction>sink</direction>
+ <presence>always</presence>
+ <details>audio/x-dts, framed=(boolean)false</details>
+ </caps>
+ <caps>
+ <name>src</name>
+ <direction>source</direction>
+ <presence>always</presence>
+ <details>audio/x-dts, framed=(boolean)true, channels=(int)[ 1, 8 ], rate=(int)[ 8000, 192000 ], depth=(int){ 14, 16 }, endianness=(int){ 1234, 4321 }</details>
+ </caps>
+ </pads>
+ </element>
+ <element>
+ <name>flacparse</name>
+ <longname>FLAC audio parser</longname>
+ <class>Codec/Parser/Audio</class>
+ <description>Parses audio with the FLAC lossless audio codec</description>
+ <author>Sebastian Dröge &lt;sebastian.droege@collabora.co.uk&gt;</author>
+ <pads>
+ <caps>
+ <name>sink</name>
+ <direction>sink</direction>
+ <presence>always</presence>
+ <details>audio/x-flac, framed=(boolean)false</details>
+ </caps>
+ <caps>
+ <name>src</name>
+ <direction>source</direction>
+ <presence>always</presence>
+ <details>audio/x-flac, framed=(boolean)true, channels=(int)[ 1, 8 ], rate=(int)[ 1, 655350 ]</details>
+ </caps>
+ </pads>
+ </element>
+ <element>
+ <name>mpegaudioparse</name>
+ <longname>MPEG1 Audio Parser</longname>
+ <class>Codec/Parser/Audio</class>
+ <description>Parses and frames mpeg1 audio streams (levels 1-3), provides seek</description>
+ <author>Jan Schmidt &lt;thaytan@mad.scientist.com&gt;,Mark Nauwelaerts &lt;mark.nauwelaerts@collabora.co.uk&gt;</author>
+ <pads>
+ <caps>
+ <name>sink</name>
+ <direction>sink</direction>
+ <presence>always</presence>
+ <details>audio/mpeg, mpegversion=(int)1, parsed=(boolean)false</details>
+ </caps>
+ <caps>
+ <name>src</name>
+ <direction>source</direction>
+ <presence>always</presence>
+ <details>audio/mpeg, mpegversion=(int)1, layer=(int)[ 1, 3 ], rate=(int)[ 8000, 48000 ], channels=(int)[ 1, 2 ], parsed=(boolean)true</details>
+ </caps>
+ </pads>
+ </element>
+ </elements>
+</plugin> \ No newline at end of file
diff --git a/docs/plugins/inspect/plugin-auparse.xml b/docs/plugins/inspect/plugin-auparse.xml
index bedf6b24f..b6ded0d6c 100644
--- a/docs/plugins/inspect/plugin-auparse.xml
+++ b/docs/plugins/inspect/plugin-auparse.xml
@@ -3,10 +3,10 @@
<description>parses au streams</description>
<filename>../../gst/auparse/.libs/libgstauparse.so</filename>
<basename>libgstauparse.so</basename>
- <version>0.10.28.1</version>
+ <version>0.10.28.2</version>
<license>LGPL</license>
<source>gst-plugins-good</source>
- <package>GStreamer Good Plug-ins git</package>
+ <package>GStreamer Good Plug-ins prerelease</package>
<origin>Unknown package origin</origin>
<elements>
<element>
diff --git a/docs/plugins/inspect/plugin-autodetect.xml b/docs/plugins/inspect/plugin-autodetect.xml
index 9b9c6a3f1..4be2fc61f 100644
--- a/docs/plugins/inspect/plugin-autodetect.xml
+++ b/docs/plugins/inspect/plugin-autodetect.xml
@@ -3,10 +3,10 @@
<description>Plugin contains auto-detection plugins for video/audio in- and outputs</description>
<filename>../../gst/autodetect/.libs/libgstautodetect.so</filename>
<basename>libgstautodetect.so</basename>
- <version>0.10.28.1</version>
+ <version>0.10.28.2</version>
<license>LGPL</license>
<source>gst-plugins-good</source>
- <package>GStreamer Good Plug-ins git</package>
+ <package>GStreamer Good Plug-ins prerelease</package>
<origin>Unknown package origin</origin>
<elements>
<element>
diff --git a/docs/plugins/inspect/plugin-avi.xml b/docs/plugins/inspect/plugin-avi.xml
index 6ee039f74..f589b3087 100644
--- a/docs/plugins/inspect/plugin-avi.xml
+++ b/docs/plugins/inspect/plugin-avi.xml
@@ -3,10 +3,10 @@
<description>AVI stream handling</description>
<filename>../../gst/avi/.libs/libgstavi.so</filename>
<basename>libgstavi.so</basename>
- <version>0.10.28.1</version>
+ <version>0.10.28.2</version>
<license>LGPL</license>
<source>gst-plugins-good</source>
- <package>GStreamer Good Plug-ins git</package>
+ <package>GStreamer Good Plug-ins prerelease</package>
<origin>Unknown package origin</origin>
<elements>
<element>
@@ -38,7 +38,7 @@
<name>video_%02d</name>
<direction>source</direction>
<presence>sometimes</presence>
- <details>video/x-3ivx, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-asus, asusversion=(int)1, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-asus, asusversion=(int)2, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-cirrus-logic-accupak, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-compressed-yuv, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-raw-rgb, bpp=(int){ 8, 24, 32 }, depth=(int){ 8, 24 }, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-divx, divxversion=(int)3, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-divx, divxversion=(int)4, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-truemotion, trueversion=(int)1, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-dv, systemstream=(boolean)false, dvversion=(int)25, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-dv, systemstream=(boolean)false, dvversion=(int)50, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-divx, divxversion=(int)5, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/mpeg, mpegversion=(int)4, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-flash-video, flvversion=(int)1, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-vp6-flash, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-h263, variant=(string)itu, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-h263, variant=(string)lucent, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-h264, variant=(string)itu, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-huffyuv, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-intel-h263, variant=(string)intel, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-raw-yuv, format=(fourcc)I420, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-indeo, indeoversion=(int)3, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-indeo, indeoversion=(int)4, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-indeo, indeoversion=(int)5, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-h263, variant=(string)lead, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-h264, variant=(string)lead, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-h263, variant=(string)microsoft, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/mpeg, mpegversion=(int)4, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; image/jpeg, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-msmpeg, msmpegversion=(int)42, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-msmpeg, msmpegversion=(int)43, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/mpeg, systemstream=(boolean)false, mpegversion=(int)1, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/mpeg, systemstream=(boolean)false, mpegversion=(int)2, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-msmpeg, msmpegversion=(int)41, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-mszh, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; image/png, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-rle, layout=(string)microsoft, depth=(int)[ 1, 64 ], framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-indeo, indeoversion=(int)2, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/sp5x, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-truemotion, trueversion=(int)2, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-camtasia, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-ultimotion, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-raw-yuv, format=(fourcc)UYVY, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-ati-vcr, vcrversion=(int)1, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-ati-vcr, vcrversion=(int)2, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-h263, variant=(string)vdolive, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-h263, variant=(string)vivo, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-vmnc, version=(int)1, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-vp3, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-h264, variant=(string)videosoft, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-wmv, wmvversion=(int)1, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-wmv, wmvversion=(int)2, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-wmv, wmvversion=(int)3, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-xvid, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-xan, wcversion=(int)4, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-raw-yuv, format=(fourcc)YUY2, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-raw-yuv, format=(fourcc)YVU9, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-zlib, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-cinepak, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-h264, variant=(string)itu, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-msvideocodec, msvideoversion=(int)1, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-h263, variant=(string)xirlink, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-dirac, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-ffv, ffvversion=(int)1, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-kmvc, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-vp5, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-vp6, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-vp6-flash, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-vp7, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-vp8, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-mimic, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-apple-video, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-theora, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-fraps, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-aasc, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-raw-yuv, format=(fourcc)YV12, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-loco, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-zmbv, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-dv, systemstream=(boolean)true; video/x-avi-unknown</details>
+ <details>video/x-3ivx, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-asus, asusversion=(int)1, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-asus, asusversion=(int)2, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-cirrus-logic-accupak, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-camstudio, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-compressed-yuv, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-raw-rgb, bpp=(int){ 8, 24, 32 }, depth=(int){ 8, 24 }, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-divx, divxversion=(int)3, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-divx, divxversion=(int)4, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-truemotion, trueversion=(int)1, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-dv, systemstream=(boolean)false, dvversion=(int)25, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-dv, systemstream=(boolean)false, dvversion=(int)50, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-divx, divxversion=(int)5, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/mpeg, mpegversion=(int)4, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-flash-video, flvversion=(int)1, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-vp6-flash, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-h263, variant=(string)itu, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-h263, variant=(string)lucent, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-h264, variant=(string)itu, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-huffyuv, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-intel-h263, variant=(string)intel, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-raw-yuv, format=(fourcc)I420, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-indeo, indeoversion=(int)3, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-indeo, indeoversion=(int)4, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-indeo, indeoversion=(int)5, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-h263, variant=(string)lead, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-h264, variant=(string)lead, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-h263, variant=(string)microsoft, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/mpeg, mpegversion=(int)4, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; image/jpeg, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-msmpeg, msmpegversion=(int)42, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-msmpeg, msmpegversion=(int)43, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/mpeg, systemstream=(boolean)false, mpegversion=(int)1, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/mpeg, systemstream=(boolean)false, mpegversion=(int)2, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-msmpeg, msmpegversion=(int)41, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-mszh, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; image/png, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-rle, layout=(string)microsoft, depth=(int)[ 1, 64 ], framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-indeo, indeoversion=(int)2, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/sp5x, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-truemotion, trueversion=(int)2, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-camtasia, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-ultimotion, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-raw-yuv, format=(fourcc)UYVY, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-ati-vcr, vcrversion=(int)1, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-ati-vcr, vcrversion=(int)2, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-h263, variant=(string)vdolive, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-h263, variant=(string)vivo, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-vmnc, version=(int)1, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-vp3, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-h264, variant=(string)videosoft, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-wmv, wmvversion=(int)1, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-wmv, wmvversion=(int)2, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-wmv, wmvversion=(int)3, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-xvid, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-xan, wcversion=(int)4, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-raw-yuv, format=(fourcc)YUY2, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-raw-yuv, format=(fourcc)YVU9, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-zlib, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-cinepak, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-h264, variant=(string)itu, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-msvideocodec, msvideoversion=(int)1, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-h263, variant=(string)xirlink, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-dirac, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-ffv, ffvversion=(int)1, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-kmvc, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-vp5, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-vp6, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-vp6-flash, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-vp7, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-vp8, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-mimic, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-apple-video, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-theora, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-fraps, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-aasc, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-raw-yuv, format=(fourcc)YV12, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-loco, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-zmbv, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-dv, systemstream=(boolean)true; video/x-avi-unknown</details>
</caps>
</pads>
</element>
diff --git a/docs/plugins/inspect/plugin-cacasink.xml b/docs/plugins/inspect/plugin-cacasink.xml
index d8ad35a0b..ae0ff25f9 100644
--- a/docs/plugins/inspect/plugin-cacasink.xml
+++ b/docs/plugins/inspect/plugin-cacasink.xml
@@ -3,10 +3,10 @@
<description>Colored ASCII Art video sink</description>
<filename>../../ext/libcaca/.libs/libgstcacasink.so</filename>
<basename>libgstcacasink.so</basename>
- <version>0.10.28.1</version>
+ <version>0.10.28.2</version>
<license>LGPL</license>
<source>gst-plugins-good</source>
- <package>GStreamer Good Plug-ins git</package>
+ <package>GStreamer Good Plug-ins prerelease</package>
<origin>Unknown package origin</origin>
<elements>
<element>
diff --git a/docs/plugins/inspect/plugin-cairo.xml b/docs/plugins/inspect/plugin-cairo.xml
index e1101ddc7..9bd41b11b 100644
--- a/docs/plugins/inspect/plugin-cairo.xml
+++ b/docs/plugins/inspect/plugin-cairo.xml
@@ -3,13 +3,34 @@
<description>Cairo-based elements</description>
<filename>../../ext/cairo/.libs/libgstcairo.so</filename>
<basename>libgstcairo.so</basename>
- <version>0.10.28.1</version>
+ <version>0.10.28.2</version>
<license>LGPL</license>
<source>gst-plugins-good</source>
- <package>GStreamer Good Plug-ins git</package>
+ <package>GStreamer Good Plug-ins prerelease</package>
<origin>Unknown package origin</origin>
<elements>
<element>
+ <name>cairooverlay</name>
+ <longname>Cairo overlay</longname>
+ <class>Filter/Editor/Video</class>
+ <description>Render overlay on a video stream using Cairo</description>
+ <author>Jon Nordby &lt;jononor@gmail.com&gt;</author>
+ <pads>
+ <caps>
+ <name>sink</name>
+ <direction>sink</direction>
+ <presence>always</presence>
+ <details>video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)65280, green_mask=(int)16711680, blue_mask=(int)-16777216, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)65280, green_mask=(int)16711680, blue_mask=(int)-16777216, alpha_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]</details>
+ </caps>
+ <caps>
+ <name>src</name>
+ <direction>source</direction>
+ <presence>always</presence>
+ <details>video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)65280, green_mask=(int)16711680, blue_mask=(int)-16777216, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)65280, green_mask=(int)16711680, blue_mask=(int)-16777216, alpha_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]</details>
+ </caps>
+ </pads>
+ </element>
+ <element>
<name>cairorender</name>
<longname>Cairo encoder</longname>
<class>Codec/Encoder</class>
diff --git a/docs/plugins/inspect/plugin-cutter.xml b/docs/plugins/inspect/plugin-cutter.xml
index 2de4dffc3..36e407e0c 100644
--- a/docs/plugins/inspect/plugin-cutter.xml
+++ b/docs/plugins/inspect/plugin-cutter.xml
@@ -3,10 +3,10 @@
<description>Audio Cutter to split audio into non-silent bits</description>
<filename>../../gst/cutter/.libs/libgstcutter.so</filename>
<basename>libgstcutter.so</basename>
- <version>0.10.28.1</version>
+ <version>0.10.28.2</version>
<license>LGPL</license>
<source>gst-plugins-good</source>
- <package>GStreamer Good Plug-ins git</package>
+ <package>GStreamer Good Plug-ins prerelease</package>
<origin>Unknown package origin</origin>
<elements>
<element>
diff --git a/docs/plugins/inspect/plugin-debug.xml b/docs/plugins/inspect/plugin-debug.xml
index f217a1399..c2ce1ef1e 100644
--- a/docs/plugins/inspect/plugin-debug.xml
+++ b/docs/plugins/inspect/plugin-debug.xml
@@ -3,10 +3,10 @@
<description>elements for testing and debugging</description>
<filename>../../gst/debugutils/.libs/libgstdebug.so</filename>
<basename>libgstdebug.so</basename>
- <version>0.10.28.1</version>
+ <version>0.10.28.2</version>
<license>LGPL</license>
<source>gst-plugins-good</source>
- <package>GStreamer Good Plug-ins git</package>
+ <package>GStreamer Good Plug-ins prerelease</package>
<origin>Unknown package origin</origin>
<elements>
<element>
diff --git a/docs/plugins/inspect/plugin-deinterlace.xml b/docs/plugins/inspect/plugin-deinterlace.xml
index 44e09aac6..6d5a7797c 100644
--- a/docs/plugins/inspect/plugin-deinterlace.xml
+++ b/docs/plugins/inspect/plugin-deinterlace.xml
@@ -3,10 +3,10 @@
<description>Deinterlacer</description>
<filename>../../gst/deinterlace/.libs/libgstdeinterlace.so</filename>
<basename>libgstdeinterlace.so</basename>
- <version>0.10.28.1</version>
+ <version>0.10.28.2</version>
<license>LGPL</license>
<source>gst-plugins-good</source>
- <package>GStreamer Good Plug-ins git</package>
+ <package>GStreamer Good Plug-ins prerelease</package>
<origin>Unknown package origin</origin>
<elements>
<element>
diff --git a/docs/plugins/inspect/plugin-dv.xml b/docs/plugins/inspect/plugin-dv.xml
index 50ebf79ac..4cf9e8ac8 100644
--- a/docs/plugins/inspect/plugin-dv.xml
+++ b/docs/plugins/inspect/plugin-dv.xml
@@ -3,10 +3,10 @@
<description>DV demuxer and decoder based on libdv (libdv.sf.net)</description>
<filename>../../ext/dv/.libs/libgstdv.so</filename>
<basename>libgstdv.so</basename>
- <version>0.10.28.1</version>
+ <version>0.10.28.2</version>
<license>LGPL</license>
<source>gst-plugins-good</source>
- <package>GStreamer Good Plug-ins git</package>
+ <package>GStreamer Good Plug-ins prerelease</package>
<origin>Unknown package origin</origin>
<elements>
<element>
diff --git a/docs/plugins/inspect/plugin-efence.xml b/docs/plugins/inspect/plugin-efence.xml
index 0bd8c3e5d..6a276399e 100644
--- a/docs/plugins/inspect/plugin-efence.xml
+++ b/docs/plugins/inspect/plugin-efence.xml
@@ -3,10 +3,10 @@
<description>This element converts a stream of normal GStreamer buffers into a stream of buffers that are allocated in such a way that out-of-bounds access to data in the buffer is more likely to cause segmentation faults. This allocation method is very similar to the debugging tool &quot;Electric Fence&quot;.</description>
<filename>../../gst/debugutils/.libs/libgstefence.so</filename>
<basename>libgstefence.so</basename>
- <version>0.10.28.1</version>
+ <version>0.10.28.2</version>
<license>LGPL</license>
<source>gst-plugins-good</source>
- <package>GStreamer Good Plug-ins git</package>
+ <package>GStreamer Good Plug-ins prerelease</package>
<origin>Unknown package origin</origin>
<elements>
<element>
diff --git a/docs/plugins/inspect/plugin-effectv.xml b/docs/plugins/inspect/plugin-effectv.xml
index 7358611c4..f9675c2af 100644
--- a/docs/plugins/inspect/plugin-effectv.xml
+++ b/docs/plugins/inspect/plugin-effectv.xml
@@ -3,10 +3,10 @@
<description>effect plugins from the effectv project</description>
<filename>../../gst/effectv/.libs/libgsteffectv.so</filename>
<basename>libgsteffectv.so</basename>
- <version>0.10.28.1</version>
+ <version>0.10.28.2</version>
<license>LGPL</license>
<source>gst-plugins-good</source>
- <package>GStreamer Good Plug-ins git</package>
+ <package>GStreamer Good Plug-ins prerelease</package>
<origin>Unknown package origin</origin>
<elements>
<element>
diff --git a/docs/plugins/inspect/plugin-equalizer.xml b/docs/plugins/inspect/plugin-equalizer.xml
index 0d97accd2..b039c8f40 100644
--- a/docs/plugins/inspect/plugin-equalizer.xml
+++ b/docs/plugins/inspect/plugin-equalizer.xml
@@ -3,10 +3,10 @@
<description>GStreamer audio equalizers</description>
<filename>../../gst/equalizer/.libs/libgstequalizer.so</filename>
<basename>libgstequalizer.so</basename>
- <version>0.10.28.1</version>
+ <version>0.10.28.2</version>
<license>LGPL</license>
<source>gst-plugins-good</source>
- <package>GStreamer Good Plug-ins git</package>
+ <package>GStreamer Good Plug-ins prerelease</package>
<origin>Unknown package origin</origin>
<elements>
<element>
diff --git a/docs/plugins/inspect/plugin-esdsink.xml b/docs/plugins/inspect/plugin-esdsink.xml
index b4f2065dc..de4476d3e 100644
--- a/docs/plugins/inspect/plugin-esdsink.xml
+++ b/docs/plugins/inspect/plugin-esdsink.xml
@@ -3,10 +3,10 @@
<description>ESD Element Plugins</description>
<filename>../../ext/esd/.libs/libgstesd.so</filename>
<basename>libgstesd.so</basename>
- <version>0.10.28.1</version>
+ <version>0.10.28.2</version>
<license>LGPL</license>
<source>gst-plugins-good</source>
- <package>GStreamer Good Plug-ins git</package>
+ <package>GStreamer Good Plug-ins prerelease</package>
<origin>Unknown package origin</origin>
<elements>
<element>
diff --git a/docs/plugins/inspect/plugin-flac.xml b/docs/plugins/inspect/plugin-flac.xml
index b793e1189..ddea6e0d8 100644
--- a/docs/plugins/inspect/plugin-flac.xml
+++ b/docs/plugins/inspect/plugin-flac.xml
@@ -3,10 +3,10 @@
<description>The FLAC Lossless compressor Codec</description>
<filename>../../ext/flac/.libs/libgstflac.so</filename>
<basename>libgstflac.so</basename>
- <version>0.10.28.1</version>
+ <version>0.10.28.2</version>
<license>LGPL</license>
<source>gst-plugins-good</source>
- <package>GStreamer Good Plug-ins git</package>
+ <package>GStreamer Good Plug-ins prerelease</package>
<origin>Unknown package origin</origin>
<elements>
<element>
diff --git a/docs/plugins/inspect/plugin-flv.xml b/docs/plugins/inspect/plugin-flv.xml
index d5cd28859..eed824170 100644
--- a/docs/plugins/inspect/plugin-flv.xml
+++ b/docs/plugins/inspect/plugin-flv.xml
@@ -3,10 +3,10 @@
<description>FLV muxing and demuxing plugin</description>
<filename>../../gst/flv/.libs/libgstflv.so</filename>
<basename>libgstflv.so</basename>
- <version>0.10.28.1</version>
+ <version>0.10.28.2</version>
<license>LGPL</license>
<source>gst-plugins-good</source>
- <package>GStreamer Good Plug-ins git</package>
+ <package>GStreamer Good Plug-ins prerelease</package>
<origin>Unknown package origin</origin>
<elements>
<element>
@@ -32,7 +32,7 @@
<name>video</name>
<direction>source</direction>
<presence>sometimes</presence>
- <details>video/x-flash-video; video/x-flash-screen; video/x-vp6-flash; video/x-vp6-alpha; video/x-h264</details>
+ <details>video/x-flash-video; video/x-flash-screen; video/x-vp6-flash; video/x-vp6-alpha; video/x-h264, stream-format=(string)avc</details>
</caps>
</pads>
</element>
@@ -53,7 +53,7 @@
<name>video</name>
<direction>sink</direction>
<presence>request</presence>
- <details>video/x-flash-video; video/x-flash-screen; video/x-vp6-flash; video/x-vp6-alpha; video/x-h264</details>
+ <details>video/x-flash-video; video/x-flash-screen; video/x-vp6-flash; video/x-vp6-alpha; video/x-h264, stream-format=(string)avc</details>
</caps>
<caps>
<name>src</name>
diff --git a/docs/plugins/inspect/plugin-flxdec.xml b/docs/plugins/inspect/plugin-flxdec.xml
index 72e3cf053..5a68a00b1 100644
--- a/docs/plugins/inspect/plugin-flxdec.xml
+++ b/docs/plugins/inspect/plugin-flxdec.xml
@@ -3,10 +3,10 @@
<description>FLC/FLI/FLX video decoder</description>
<filename>../../gst/flx/.libs/libgstflxdec.so</filename>
<basename>libgstflxdec.so</basename>
- <version>0.10.28.1</version>
+ <version>0.10.28.2</version>
<license>LGPL</license>
<source>gst-plugins-good</source>
- <package>GStreamer Good Plug-ins git</package>
+ <package>GStreamer Good Plug-ins prerelease</package>
<origin>Unknown package origin</origin>
<elements>
<element>
diff --git a/docs/plugins/inspect/plugin-gconfelements.xml b/docs/plugins/inspect/plugin-gconfelements.xml
index c5f9df818..ab0b2c548 100644
--- a/docs/plugins/inspect/plugin-gconfelements.xml
+++ b/docs/plugins/inspect/plugin-gconfelements.xml
@@ -3,10 +3,10 @@
<description>elements wrapping the GStreamer/GConf audio/video output settings</description>
<filename>../../ext/gconf/.libs/libgstgconfelements.so</filename>
<basename>libgstgconfelements.so</basename>
- <version>0.10.28.1</version>
+ <version>0.10.28.2</version>
<license>LGPL</license>
<source>gst-plugins-good</source>
- <package>GStreamer Good Plug-ins git</package>
+ <package>GStreamer Good Plug-ins prerelease</package>
<origin>Unknown package origin</origin>
<elements>
<element>
diff --git a/docs/plugins/inspect/plugin-gdkpixbuf.xml b/docs/plugins/inspect/plugin-gdkpixbuf.xml
index bea162e70..70f0286fc 100644
--- a/docs/plugins/inspect/plugin-gdkpixbuf.xml
+++ b/docs/plugins/inspect/plugin-gdkpixbuf.xml
@@ -3,10 +3,10 @@
<description>GdkPixbuf-based image decoder, scaler and sink</description>
<filename>../../ext/gdk_pixbuf/.libs/libgstgdkpixbuf.so</filename>
<basename>libgstgdkpixbuf.so</basename>
- <version>0.10.28.1</version>
+ <version>0.10.28.2</version>
<license>LGPL</license>
<source>gst-plugins-good</source>
- <package>GStreamer Good Plug-ins git</package>
+ <package>GStreamer Good Plug-ins prerelease</package>
<origin>Unknown package origin</origin>
<elements>
<element>
diff --git a/docs/plugins/inspect/plugin-goom.xml b/docs/plugins/inspect/plugin-goom.xml
index f4b19432b..1538fa0ed 100644
--- a/docs/plugins/inspect/plugin-goom.xml
+++ b/docs/plugins/inspect/plugin-goom.xml
@@ -3,10 +3,10 @@
<description>GOOM visualization filter</description>
<filename>../../gst/goom/.libs/libgstgoom.so</filename>
<basename>libgstgoom.so</basename>
- <version>0.10.28.1</version>
+ <version>0.10.28.2</version>
<license>LGPL</license>
<source>gst-plugins-good</source>
- <package>GStreamer Good Plug-ins git</package>
+ <package>GStreamer Good Plug-ins prerelease</package>
<origin>Unknown package origin</origin>
<elements>
<element>
diff --git a/docs/plugins/inspect/plugin-goom2k1.xml b/docs/plugins/inspect/plugin-goom2k1.xml
index c6c97a8e7..03d19eaf0 100644
--- a/docs/plugins/inspect/plugin-goom2k1.xml
+++ b/docs/plugins/inspect/plugin-goom2k1.xml
@@ -3,10 +3,10 @@
<description>GOOM 2k1 visualization filter</description>
<filename>../../gst/goom2k1/.libs/libgstgoom2k1.so</filename>
<basename>libgstgoom2k1.so</basename>
- <version>0.10.28.1</version>
+ <version>0.10.28.2</version>
<license>LGPL</license>
<source>gst-plugins-good</source>
- <package>GStreamer Good Plug-ins git</package>
+ <package>GStreamer Good Plug-ins prerelease</package>
<origin>Unknown package origin</origin>
<elements>
<element>
diff --git a/docs/plugins/inspect/plugin-gstrtpmanager.xml b/docs/plugins/inspect/plugin-gstrtpmanager.xml
index 9619ac6b1..35e97cd44 100644
--- a/docs/plugins/inspect/plugin-gstrtpmanager.xml
+++ b/docs/plugins/inspect/plugin-gstrtpmanager.xml
@@ -3,10 +3,10 @@
<description>RTP session management plugin library</description>
<filename>../../gst/rtpmanager/.libs/libgstrtpmanager.so</filename>
<basename>libgstrtpmanager.so</basename>
- <version>0.10.28.1</version>
+ <version>0.10.28.2</version>
<license>LGPL</license>
<source>gst-plugins-good</source>
- <package>GStreamer Good Plug-ins git</package>
+ <package>GStreamer Good Plug-ins prerelease</package>
<origin>Unknown package origin</origin>
<elements>
<element>
diff --git a/docs/plugins/inspect/plugin-halelements.xml b/docs/plugins/inspect/plugin-halelements.xml
index 3c0715a32..dda60c2c7 100644
--- a/docs/plugins/inspect/plugin-halelements.xml
+++ b/docs/plugins/inspect/plugin-halelements.xml
@@ -3,10 +3,10 @@
<description>elements wrapping the GStreamer/HAL audio input/output devices</description>
<filename>../../ext/hal/.libs/libgsthalelements.so</filename>
<basename>libgsthalelements.so</basename>
- <version>0.10.28.1</version>
+ <version>0.10.28.2</version>
<license>LGPL</license>
<source>gst-plugins-good</source>
- <package>GStreamer Good Plug-ins git</package>
+ <package>GStreamer Good Plug-ins prerelease</package>
<origin>Unknown package origin</origin>
<elements>
<element>
diff --git a/docs/plugins/inspect/plugin-icydemux.xml b/docs/plugins/inspect/plugin-icydemux.xml
index e118be9f1..41cc97c5b 100644
--- a/docs/plugins/inspect/plugin-icydemux.xml
+++ b/docs/plugins/inspect/plugin-icydemux.xml
@@ -3,10 +3,10 @@
<description>Demux ICY tags from a stream</description>
<filename>../../gst/icydemux/.libs/libgsticydemux.so</filename>
<basename>libgsticydemux.so</basename>
- <version>0.10.28.1</version>
+ <version>0.10.28.2</version>
<license>LGPL</license>
<source>gst-plugins-good</source>
- <package>GStreamer Good Plug-ins git</package>
+ <package>GStreamer Good Plug-ins prerelease</package>
<origin>Unknown package origin</origin>
<elements>
<element>
diff --git a/docs/plugins/inspect/plugin-id3demux.xml b/docs/plugins/inspect/plugin-id3demux.xml
index 453b114de..867d0dd54 100644
--- a/docs/plugins/inspect/plugin-id3demux.xml
+++ b/docs/plugins/inspect/plugin-id3demux.xml
@@ -3,10 +3,10 @@
<description>Demux ID3v1 and ID3v2 tags from a file</description>
<filename>../../gst/id3demux/.libs/libgstid3demux.so</filename>
<basename>libgstid3demux.so</basename>
- <version>0.10.28.1</version>
+ <version>0.10.28.2</version>
<license>LGPL</license>
<source>gst-plugins-good</source>
- <package>GStreamer Good Plug-ins git</package>
+ <package>GStreamer Good Plug-ins prerelease</package>
<origin>Unknown package origin</origin>
<elements>
<element>
diff --git a/docs/plugins/inspect/plugin-imagefreeze.xml b/docs/plugins/inspect/plugin-imagefreeze.xml
index b52167049..53b8d3ba9 100644
--- a/docs/plugins/inspect/plugin-imagefreeze.xml
+++ b/docs/plugins/inspect/plugin-imagefreeze.xml
@@ -3,10 +3,10 @@
<description>Still frame stream generator</description>
<filename>../../gst/imagefreeze/.libs/libgstimagefreeze.so</filename>
<basename>libgstimagefreeze.so</basename>
- <version>0.10.28.1</version>
+ <version>0.10.28.2</version>
<license>LGPL</license>
<source>gst-plugins-good</source>
- <package>GStreamer Good Plug-ins git</package>
+ <package>GStreamer Good Plug-ins prerelease</package>
<origin>Unknown package origin</origin>
<elements>
<element>
diff --git a/docs/plugins/inspect/plugin-interleave.xml b/docs/plugins/inspect/plugin-interleave.xml
index 0bf5b6863..a0887907b 100644
--- a/docs/plugins/inspect/plugin-interleave.xml
+++ b/docs/plugins/inspect/plugin-interleave.xml
@@ -3,10 +3,10 @@
<description>Audio interleaver/deinterleaver</description>
<filename>../../gst/interleave/.libs/libgstinterleave.so</filename>
<basename>libgstinterleave.so</basename>
- <version>0.10.28.1</version>
+ <version>0.10.28.2</version>
<license>LGPL</license>
<source>gst-plugins-good</source>
- <package>GStreamer Good Plug-ins git</package>
+ <package>GStreamer Good Plug-ins prerelease</package>
<origin>Unknown package origin</origin>
<elements>
<element>
diff --git a/docs/plugins/inspect/plugin-jack.xml b/docs/plugins/inspect/plugin-jack.xml
index 60088fa12..1f5e285e8 100644
--- a/docs/plugins/inspect/plugin-jack.xml
+++ b/docs/plugins/inspect/plugin-jack.xml
@@ -3,10 +3,10 @@
<description>JACK audio elements</description>
<filename>../../ext/jack/.libs/libgstjack.so</filename>
<basename>libgstjack.so</basename>
- <version>0.10.28.1</version>
+ <version>0.10.28.2</version>
<license>LGPL</license>
<source>gst-plugins-good</source>
- <package>GStreamer Good Plug-ins git</package>
+ <package>GStreamer Good Plug-ins prerelease</package>
<origin>Unknown package origin</origin>
<elements>
<element>
diff --git a/docs/plugins/inspect/plugin-jpeg.xml b/docs/plugins/inspect/plugin-jpeg.xml
index ab8ca7175..0b43211ce 100644
--- a/docs/plugins/inspect/plugin-jpeg.xml
+++ b/docs/plugins/inspect/plugin-jpeg.xml
@@ -3,10 +3,10 @@
<description>JPeg plugin library</description>
<filename>../../ext/jpeg/.libs/libgstjpeg.so</filename>
<basename>libgstjpeg.so</basename>
- <version>0.10.28.1</version>
+ <version>0.10.28.2</version>
<license>LGPL</license>
<source>gst-plugins-good</source>
- <package>GStreamer Good Plug-ins git</package>
+ <package>GStreamer Good Plug-ins prerelease</package>
<origin>Unknown package origin</origin>
<elements>
<element>
diff --git a/docs/plugins/inspect/plugin-level.xml b/docs/plugins/inspect/plugin-level.xml
index 294a796f0..8a697e05f 100644
--- a/docs/plugins/inspect/plugin-level.xml
+++ b/docs/plugins/inspect/plugin-level.xml
@@ -3,10 +3,10 @@
<description>Audio level plugin</description>
<filename>../../gst/level/.libs/libgstlevel.so</filename>
<basename>libgstlevel.so</basename>
- <version>0.10.28.1</version>
+ <version>0.10.28.2</version>
<license>LGPL</license>
<source>gst-plugins-good</source>
- <package>GStreamer Good Plug-ins git</package>
+ <package>GStreamer Good Plug-ins prerelease</package>
<origin>Unknown package origin</origin>
<elements>
<element>
diff --git a/docs/plugins/inspect/plugin-matroska.xml b/docs/plugins/inspect/plugin-matroska.xml
index ea9518758..78b0be159 100644
--- a/docs/plugins/inspect/plugin-matroska.xml
+++ b/docs/plugins/inspect/plugin-matroska.xml
@@ -3,10 +3,10 @@
<description>Matroska and WebM stream handling</description>
<filename>../../gst/matroska/.libs/libgstmatroska.so</filename>
<basename>libgstmatroska.so</basename>
- <version>0.10.28.1</version>
+ <version>0.10.28.2</version>
<license>LGPL</license>
<source>gst-plugins-good</source>
- <package>GStreamer Good Plug-ins git</package>
+ <package>GStreamer Good Plug-ins prerelease</package>
<origin>Unknown package origin</origin>
<elements>
<element>
@@ -53,7 +53,7 @@
<name>audio_%d</name>
<direction>sink</direction>
<presence>request</presence>
- <details>audio/mpeg, mpegversion=(int)1, layer=(int)[ 1, 3 ], stream-format=(string){ raw }, channels=(int)[ 1, 2147483647 ], rate=(int)[ 1, 2147483647 ]; audio/mpeg, mpegversion=(int){ 2, 4 }, channels=(int)[ 1, 2147483647 ], rate=(int)[ 1, 2147483647 ]; audio/x-ac3, channels=(int)[ 1, 2147483647 ], rate=(int)[ 1, 2147483647 ]; audio/x-eac3, channels=(int)[ 1, 2147483647 ], rate=(int)[ 1, 2147483647 ]; audio/x-dts, channels=(int)[ 1, 2147483647 ], rate=(int)[ 1, 2147483647 ]; audio/x-vorbis, channels=(int)[ 1, 2147483647 ], rate=(int)[ 1, 2147483647 ]; audio/x-flac, channels=(int)[ 1, 2147483647 ], rate=(int)[ 1, 2147483647 ]; audio/x-speex, channels=(int)[ 1, 2147483647 ], rate=(int)[ 1, 2147483647 ]; audio/x-raw-int, width=(int)8, depth=(int)8, signed=(boolean)false, channels=(int)[ 1, 2147483647 ], rate=(int)[ 1, 2147483647 ]; audio/x-raw-int, width=(int)16, depth=(int)16, endianness=(int){ 4321, 1234 }, signed=(boolean)true, channels=(int)[ 1, 2147483647 ], rate=(int)[ 1, 2147483647 ]; audio/x-raw-int, width=(int)24, depth=(int)24, endianness=(int){ 4321, 1234 }, signed=(boolean)true, channels=(int)[ 1, 2147483647 ], rate=(int)[ 1, 2147483647 ]; audio/x-raw-int, width=(int)32, depth=(int)32, endianness=(int){ 4321, 1234 }, signed=(boolean)true, channels=(int)[ 1, 2147483647 ], rate=(int)[ 1, 2147483647 ]; audio/x-raw-float, width=(int)[ 32, 64 ], endianness=(int)1234, channels=(int)[ 1, 2147483647 ], rate=(int)[ 1, 2147483647 ]; audio/x-tta, width=(int){ 8, 16, 24 }, channels=(int){ 1, 2 }, rate=(int)[ 8000, 96000 ]; audio/x-pn-realaudio, raversion=(int){ 1, 2, 8 }, channels=(int)[ 1, 2147483647 ], rate=(int)[ 1, 2147483647 ]; audio/x-wma, wmaversion=(int)[ 1, 3 ], block_align=(int)[ 0, 65535 ], bitrate=(int)[ 0, 524288 ], channels=(int)[ 1, 2147483647 ], rate=(int)[ 1, 2147483647 ]</details>
+ <details>audio/mpeg, mpegversion=(int)1, layer=(int)[ 1, 3 ], stream-format=(string){ raw }, channels=(int)[ 1, 2147483647 ], rate=(int)[ 1, 2147483647 ]; audio/mpeg, mpegversion=(int){ 2, 4 }, channels=(int)[ 1, 2147483647 ], rate=(int)[ 1, 2147483647 ]; audio/x-ac3, channels=(int)[ 1, 2147483647 ], rate=(int)[ 1, 2147483647 ]; audio/x-eac3, channels=(int)[ 1, 2147483647 ], rate=(int)[ 1, 2147483647 ]; audio/x-dts, channels=(int)[ 1, 2147483647 ], rate=(int)[ 1, 2147483647 ]; audio/x-vorbis, channels=(int)[ 1, 2147483647 ], rate=(int)[ 1, 2147483647 ]; audio/x-flac, channels=(int)[ 1, 2147483647 ], rate=(int)[ 1, 2147483647 ]; audio/x-speex, channels=(int)[ 1, 2147483647 ], rate=(int)[ 1, 2147483647 ]; audio/x-raw-int, width=(int)8, depth=(int)8, signed=(boolean)false, channels=(int)[ 1, 2147483647 ], rate=(int)[ 1, 2147483647 ]; audio/x-raw-int, width=(int)16, depth=(int)16, endianness=(int){ 4321, 1234 }, signed=(boolean)true, channels=(int)[ 1, 2147483647 ], rate=(int)[ 1, 2147483647 ]; audio/x-raw-int, width=(int)24, depth=(int)24, endianness=(int){ 4321, 1234 }, signed=(boolean)true, channels=(int)[ 1, 2147483647 ], rate=(int)[ 1, 2147483647 ]; audio/x-raw-int, width=(int)32, depth=(int)32, endianness=(int){ 4321, 1234 }, signed=(boolean)true, channels=(int)[ 1, 2147483647 ], rate=(int)[ 1, 2147483647 ]; audio/x-raw-float, width=(int)[ 32, 64 ], endianness=(int)1234, channels=(int)[ 1, 2147483647 ], rate=(int)[ 1, 2147483647 ]; audio/x-tta, width=(int){ 8, 16, 24 }, channels=(int){ 1, 2 }, rate=(int)[ 8000, 96000 ]; audio/x-pn-realaudio, raversion=(int){ 1, 2, 8 }, channels=(int)[ 1, 2147483647 ], rate=(int)[ 1, 2147483647 ]; audio/x-wma, wmaversion=(int)[ 1, 3 ], block_align=(int)[ 0, 65535 ], bitrate=(int)[ 0, 524288 ], channels=(int)[ 1, 2147483647 ], rate=(int)[ 1, 2147483647 ]; audio/x-alaw, channels=(int){ 1, 2 }, rate=(int)[ 8000, 192000 ]; audio/x-mulaw, channels=(int){ 1, 2 }, rate=(int)[ 8000, 192000 ]</details>
</caps>
<caps>
<name>subtitle_%d</name>
diff --git a/docs/plugins/inspect/plugin-monoscope.xml b/docs/plugins/inspect/plugin-monoscope.xml
index 0771febb2..b623616cb 100644
--- a/docs/plugins/inspect/plugin-monoscope.xml
+++ b/docs/plugins/inspect/plugin-monoscope.xml
@@ -3,10 +3,10 @@
<description>Monoscope visualization</description>
<filename>../../gst/monoscope/.libs/libgstmonoscope.so</filename>
<basename>libgstmonoscope.so</basename>
- <version>0.10.27.1</version>
+ <version>0.10.28.2</version>
<license>LGPL</license>
<source>gst-plugins-good</source>
- <package>GStreamer Good Plug-ins git</package>
+ <package>GStreamer Good Plug-ins prerelease</package>
<origin>Unknown package origin</origin>
<elements>
<element>
diff --git a/docs/plugins/inspect/plugin-mulaw.xml b/docs/plugins/inspect/plugin-mulaw.xml
index b7b1d32b5..1e67f12b4 100644
--- a/docs/plugins/inspect/plugin-mulaw.xml
+++ b/docs/plugins/inspect/plugin-mulaw.xml
@@ -3,10 +3,10 @@
<description>MuLaw audio conversion routines</description>
<filename>../../gst/law/.libs/libgstmulaw.so</filename>
<basename>libgstmulaw.so</basename>
- <version>0.10.28.1</version>
+ <version>0.10.28.2</version>
<license>LGPL</license>
<source>gst-plugins-good</source>
- <package>GStreamer Good Plug-ins git</package>
+ <package>GStreamer Good Plug-ins prerelease</package>
<origin>Unknown package origin</origin>
<elements>
<element>
diff --git a/docs/plugins/inspect/plugin-multifile.xml b/docs/plugins/inspect/plugin-multifile.xml
index 0e48941a6..0b0037d06 100644
--- a/docs/plugins/inspect/plugin-multifile.xml
+++ b/docs/plugins/inspect/plugin-multifile.xml
@@ -3,10 +3,10 @@
<description>Reads/Writes buffers from/to sequentially named files</description>
<filename>../../gst/multifile/.libs/libgstmultifile.so</filename>
<basename>libgstmultifile.so</basename>
- <version>0.10.28.1</version>
+ <version>0.10.28.2</version>
<license>LGPL</license>
<source>gst-plugins-good</source>
- <package>GStreamer Good Plug-ins git</package>
+ <package>GStreamer Good Plug-ins prerelease</package>
<origin>Unknown package origin</origin>
<elements>
<element>
diff --git a/docs/plugins/inspect/plugin-multipart.xml b/docs/plugins/inspect/plugin-multipart.xml
index c5f93e9d8..64fcd8ebc 100644
--- a/docs/plugins/inspect/plugin-multipart.xml
+++ b/docs/plugins/inspect/plugin-multipart.xml
@@ -3,10 +3,10 @@
<description>multipart stream manipulation</description>
<filename>../../gst/multipart/.libs/libgstmultipart.so</filename>
<basename>libgstmultipart.so</basename>
- <version>0.10.28.1</version>
+ <version>0.10.28.2</version>
<license>LGPL</license>
<source>gst-plugins-good</source>
- <package>GStreamer Good Plug-ins git</package>
+ <package>GStreamer Good Plug-ins prerelease</package>
<origin>Unknown package origin</origin>
<elements>
<element>
diff --git a/docs/plugins/inspect/plugin-navigationtest.xml b/docs/plugins/inspect/plugin-navigationtest.xml
index bfe5bf817..84f292994 100644
--- a/docs/plugins/inspect/plugin-navigationtest.xml
+++ b/docs/plugins/inspect/plugin-navigationtest.xml
@@ -3,10 +3,10 @@
<description>Template for a video filter</description>
<filename>../../gst/debugutils/.libs/libgstnavigationtest.so</filename>
<basename>libgstnavigationtest.so</basename>
- <version>0.10.28.1</version>
+ <version>0.10.28.2</version>
<license>LGPL</license>
<source>gst-plugins-good</source>
- <package>GStreamer Good Plug-ins git</package>
+ <package>GStreamer Good Plug-ins prerelease</package>
<origin>Unknown package origin</origin>
<elements>
<element>
diff --git a/docs/plugins/inspect/plugin-oss4.xml b/docs/plugins/inspect/plugin-oss4.xml
index 46b6bf38e..eea1aaafa 100644
--- a/docs/plugins/inspect/plugin-oss4.xml
+++ b/docs/plugins/inspect/plugin-oss4.xml
@@ -3,10 +3,10 @@
<description>Open Sound System (OSS) version 4 support for GStreamer</description>
<filename>../../sys/oss4/.libs/libgstoss4audio.so</filename>
<basename>libgstoss4audio.so</basename>
- <version>0.10.28.1</version>
+ <version>0.10.28.2</version>
<license>LGPL</license>
<source>gst-plugins-good</source>
- <package>GStreamer Good Plug-ins git</package>
+ <package>GStreamer Good Plug-ins prerelease</package>
<origin>Unknown package origin</origin>
<elements>
<element>
diff --git a/docs/plugins/inspect/plugin-ossaudio.xml b/docs/plugins/inspect/plugin-ossaudio.xml
index c5339354c..8e3100dae 100644
--- a/docs/plugins/inspect/plugin-ossaudio.xml
+++ b/docs/plugins/inspect/plugin-ossaudio.xml
@@ -3,10 +3,10 @@
<description>OSS (Open Sound System) support for GStreamer</description>
<filename>../../sys/oss/.libs/libgstossaudio.so</filename>
<basename>libgstossaudio.so</basename>
- <version>0.10.28.1</version>
+ <version>0.10.28.2</version>
<license>LGPL</license>
<source>gst-plugins-good</source>
- <package>GStreamer Good Plug-ins git</package>
+ <package>GStreamer Good Plug-ins prerelease</package>
<origin>Unknown package origin</origin>
<elements>
<element>
diff --git a/docs/plugins/inspect/plugin-png.xml b/docs/plugins/inspect/plugin-png.xml
index fa8d3c749..8fa2ac876 100644
--- a/docs/plugins/inspect/plugin-png.xml
+++ b/docs/plugins/inspect/plugin-png.xml
@@ -3,10 +3,10 @@
<description>PNG plugin library</description>
<filename>../../ext/libpng/.libs/libgstpng.so</filename>
<basename>libgstpng.so</basename>
- <version>0.10.28.1</version>
+ <version>0.10.28.2</version>
<license>LGPL</license>
<source>gst-plugins-good</source>
- <package>GStreamer Good Plug-ins git</package>
+ <package>GStreamer Good Plug-ins prerelease</package>
<origin>Unknown package origin</origin>
<elements>
<element>
@@ -26,7 +26,7 @@
<name>src</name>
<direction>source</direction>
<presence>always</presence>
- <details>video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)-16777216, green_mask=(int)16711680, blue_mask=(int)65280, alpha_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)24, depth=(int)24, endianness=(int)4321, red_mask=(int)16711680, green_mask=(int)65280, blue_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]</details>
+ <details>video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)-16777216, green_mask=(int)16711680, blue_mask=(int)65280, alpha_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)24, depth=(int)24, endianness=(int)4321, red_mask=(int)16711680, green_mask=(int)65280, blue_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)64, depth=(int)64, endianness=(int)4321, red_mask=(int)16711680, green_mask=(int)65280, blue_mask=(int)255, alpha_mask=(int)-16777216, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]</details>
</caps>
</pads>
</element>
diff --git a/docs/plugins/inspect/plugin-pulseaudio.xml b/docs/plugins/inspect/plugin-pulseaudio.xml
index 21723727b..50d9d7952 100644
--- a/docs/plugins/inspect/plugin-pulseaudio.xml
+++ b/docs/plugins/inspect/plugin-pulseaudio.xml
@@ -3,10 +3,10 @@
<description>PulseAudio plugin library</description>
<filename>../../ext/pulse/.libs/libgstpulse.so</filename>
<basename>libgstpulse.so</basename>
- <version>0.10.28.1</version>
+ <version>0.10.28.2</version>
<license>LGPL</license>
<source>gst-plugins-good</source>
- <package>GStreamer Good Plug-ins git</package>
+ <package>GStreamer Good Plug-ins prerelease</package>
<origin>Unknown package origin</origin>
<elements>
<element>
diff --git a/docs/plugins/inspect/plugin-quicktime.xml b/docs/plugins/inspect/plugin-quicktime.xml
index f9b98162d..74eee4ecf 100644
--- a/docs/plugins/inspect/plugin-quicktime.xml
+++ b/docs/plugins/inspect/plugin-quicktime.xml
@@ -1,15 +1,123 @@
<plugin>
<name>quicktime</name>
<description>Quicktime support</description>
- <filename>../../gst/qtdemux/.libs/libgstqtdemux.so</filename>
+ <filename>../../gst/quicktime/.libs/libgstqtdemux.so</filename>
<basename>libgstqtdemux.so</basename>
- <version>0.10.28.1</version>
+ <version>0.10.28.2</version>
<license>LGPL</license>
<source>gst-plugins-good</source>
- <package>GStreamer Good Plug-ins git</package>
+ <package>GStreamer Good Plug-ins prerelease</package>
<origin>Unknown package origin</origin>
<elements>
<element>
+ <name>gppmux</name>
+ <longname>3GPP Muxer</longname>
+ <class>Codec/Muxer</class>
+ <description>Multiplex audio and video into a 3GPP file</description>
+ <author>Thiago Sousa Santos &lt;thiagoss@embedded.ufcg.edu.br&gt;</author>
+ <pads>
+ <caps>
+ <name>audio_%d</name>
+ <direction>sink</direction>
+ <presence>request</presence>
+ <details>audio/AMR, rate=(int)8000, channels=(int)[ 1, 2 ]; audio/AMR-WB, rate=(int)16000, channels=(int)[ 1, 2 ]; audio/mpeg, mpegversion=(int)1, layer=(int)3, channels=(int)[ 1, 2 ], rate=(int)[ 1, 2147483647 ]; audio/mpeg, mpegversion=(int)4, stream-format=(string)raw, channels=(int)[ 1, 8 ], rate=(int)[ 1, 2147483647 ]</details>
+ </caps>
+ <caps>
+ <name>video_%d</name>
+ <direction>sink</direction>
+ <presence>request</presence>
+ <details>video/x-h263, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/mpeg, mpegversion=(int)4, systemstream=(boolean)false, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-divx, divxversion=(int)5, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-h264, stream-format=(string)avc, alignment=(string)au, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(fraction)[ 0/1, 2147483647/1 ]</details>
+ </caps>
+ <caps>
+ <name>src</name>
+ <direction>source</direction>
+ <presence>always</presence>
+ <details>video/quicktime, variant=(string)3gpp</details>
+ </caps>
+ </pads>
+ </element>
+ <element>
+ <name>ismlmux</name>
+ <longname>ISML Muxer</longname>
+ <class>Codec/Muxer</class>
+ <description>Multiplex audio and video into a ISML file</description>
+ <author>Thiago Sousa Santos &lt;thiagoss@embedded.ufcg.edu.br&gt;</author>
+ <pads>
+ <caps>
+ <name>audio_%d</name>
+ <direction>sink</direction>
+ <presence>request</presence>
+ <details>audio/mpeg, mpegversion=(int)1, layer=(int)3, channels=(int)[ 1, 2 ], rate=(int)[ 1, 2147483647 ]; audio/mpeg, mpegversion=(int)4, stream-format=(string)raw, channels=(int)[ 1, 8 ], rate=(int)[ 1, 2147483647 ]</details>
+ </caps>
+ <caps>
+ <name>video_%d</name>
+ <direction>sink</direction>
+ <presence>request</presence>
+ <details>video/mpeg, mpegversion=(int)4, systemstream=(boolean)false, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-divx, divxversion=(int)5, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-h264, stream-format=(string)avc, alignment=(string)au, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(fraction)[ 0/1, 2147483647/1 ]</details>
+ </caps>
+ <caps>
+ <name>src</name>
+ <direction>source</direction>
+ <presence>always</presence>
+ <details>video/quicktime, variant=(string)iso</details>
+ </caps>
+ </pads>
+ </element>
+ <element>
+ <name>mj2mux</name>
+ <longname>MJ2 Muxer</longname>
+ <class>Codec/Muxer</class>
+ <description>Multiplex audio and video into a MJ2 file</description>
+ <author>Thiago Sousa Santos &lt;thiagoss@embedded.ufcg.edu.br&gt;</author>
+ <pads>
+ <caps>
+ <name>audio_%d</name>
+ <direction>sink</direction>
+ <presence>request</presence>
+ <details>audio/x-raw-int, width=(int)8, depth=(int)8, channels=(int)[ 1, 2 ], rate=(int)[ 1, 2147483647 ], signed=(boolean){ true, false }; audio/x-raw-int, width=(int)16, depth=(int)16, endianness=(int){ 4321, 1234 }, channels=(int)[ 1, 2 ], rate=(int)[ 1, 2147483647 ], signed=(boolean)true</details>
+ </caps>
+ <caps>
+ <name>video_%d</name>
+ <direction>sink</direction>
+ <presence>request</presence>
+ <details>image/x-j2c, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; image/x-jpc, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(fraction)[ 0/1, 2147483647/1 ]</details>
+ </caps>
+ <caps>
+ <name>src</name>
+ <direction>source</direction>
+ <presence>always</presence>
+ <details>video/mj2</details>
+ </caps>
+ </pads>
+ </element>
+ <element>
+ <name>mp4mux</name>
+ <longname>MP4 Muxer</longname>
+ <class>Codec/Muxer</class>
+ <description>Multiplex audio and video into a MP4 file</description>
+ <author>Thiago Sousa Santos &lt;thiagoss@embedded.ufcg.edu.br&gt;</author>
+ <pads>
+ <caps>
+ <name>audio_%d</name>
+ <direction>sink</direction>
+ <presence>request</presence>
+ <details>audio/mpeg, mpegversion=(int)1, layer=(int)3, channels=(int)[ 1, 2 ], rate=(int)[ 1, 2147483647 ]; audio/mpeg, mpegversion=(int)4, stream-format=(string)raw, channels=(int)[ 1, 8 ], rate=(int)[ 1, 2147483647 ]; audio/x-alac, channels=(int)[ 1, 2 ], rate=(int)[ 1, 2147483647 ]</details>
+ </caps>
+ <caps>
+ <name>video_%d</name>
+ <direction>sink</direction>
+ <presence>request</presence>
+ <details>video/mpeg, mpegversion=(int)4, systemstream=(boolean)false, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-divx, divxversion=(int)5, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-h264, stream-format=(string)avc, alignment=(string)au, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-mp4-part, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(fraction)[ 0/1, 2147483647/1 ]</details>
+ </caps>
+ <caps>
+ <name>src</name>
+ <direction>source</direction>
+ <presence>always</presence>
+ <details>video/quicktime, variant=(string)iso</details>
+ </caps>
+ </pads>
+ </element>
+ <element>
<name>qtdemux</name>
<longname>QuickTime demuxer</longname>
<class>Codec/Demuxer</class>
@@ -43,6 +151,42 @@
</pads>
</element>
<element>
+ <name>qtmoovrecover</name>
+ <longname>QT Moov Recover</longname>
+ <class>Util</class>
+ <description>Recovers unfinished qtmux files</description>
+ <author>Thiago Santos &lt;thiago.sousa.santos@collabora.co.uk&gt;</author>
+ <pads>
+ </pads>
+ </element>
+ <element>
+ <name>qtmux</name>
+ <longname>QuickTime Muxer</longname>
+ <class>Codec/Muxer</class>
+ <description>Multiplex audio and video into a QuickTime file</description>
+ <author>Thiago Sousa Santos &lt;thiagoss@embedded.ufcg.edu.br&gt;</author>
+ <pads>
+ <caps>
+ <name>audio_%d</name>
+ <direction>sink</direction>
+ <presence>request</presence>
+ <details>audio/x-raw-int, width=(int)8, depth=(int)8, channels=(int)[ 1, 2 ], rate=(int)[ 1, 2147483647 ], signed=(boolean){ true, false }; audio/x-raw-int, width=(int)16, depth=(int)16, endianness=(int){ 4321, 1234 }, channels=(int)[ 1, 2 ], rate=(int)[ 1, 2147483647 ], signed=(boolean)true; audio/x-raw-int, width=(int)24, depth=(int)24, endianness=(int){ 4321, 1234 }, channels=(int)[ 1, 2 ], rate=(int)[ 1, 2147483647 ], signed=(boolean)true; audio/x-raw-int, width=(int)32, depth=(int)32, endianness=(int){ 4321, 1234 }, channels=(int)[ 1, 2 ], rate=(int)[ 1, 2147483647 ], signed=(boolean)true; audio/mpeg, mpegversion=(int)1, layer=(int)3, channels=(int)[ 1, 2 ], rate=(int)[ 1, 2147483647 ]; audio/mpeg, mpegversion=(int)4, stream-format=(string)raw, channels=(int)[ 1, 8 ], rate=(int)[ 1, 2147483647 ]; audio/x-adpcm, layout=(string)dvi, block_align=(int)[ 64, 8096 ], channels=(int)[ 1, 2 ], rate=(int)[ 1, 2147483647 ]; audio/x-alaw, channels=(int)[ 1, 2 ], rate=(int)[ 1, 2147483647 ]; audio/AMR, rate=(int)8000, channels=(int)[ 1, 2 ]; audio/AMR-WB, rate=(int)16000, channels=(int)[ 1, 2 ]; audio/x-alac, channels=(int)[ 1, 2 ], rate=(int)[ 1, 2147483647 ]</details>
+ </caps>
+ <caps>
+ <name>video_%d</name>
+ <direction>sink</direction>
+ <presence>request</presence>
+ <details>video/x-raw-rgb, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)UYVY, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/mpeg, mpegversion=(int)4, systemstream=(boolean)false, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-divx, divxversion=(int)5, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-h263, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-h264, stream-format=(string)avc, alignment=(string)au, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-svq, svqversion=(int)3, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-dv, systemstream=(boolean)false, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; image/jpeg, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-vp8, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-qt-part, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(fraction)[ 0/1, 2147483647/1 ]</details>
+ </caps>
+ <caps>
+ <name>src</name>
+ <direction>source</direction>
+ <presence>always</presence>
+ <details>video/quicktime, variant=(string)apple; video/quicktime</details>
+ </caps>
+ </pads>
+ </element>
+ <element>
<name>rtpxqtdepay</name>
<longname>RTP packet depayloader</longname>
<class>Codec/Depayloader/Network</class>
diff --git a/docs/plugins/inspect/plugin-replaygain.xml b/docs/plugins/inspect/plugin-replaygain.xml
index e9343f8bf..45e7461f1 100644
--- a/docs/plugins/inspect/plugin-replaygain.xml
+++ b/docs/plugins/inspect/plugin-replaygain.xml
@@ -3,10 +3,10 @@
<description>ReplayGain volume normalization</description>
<filename>../../gst/replaygain/.libs/libgstreplaygain.so</filename>
<basename>libgstreplaygain.so</basename>
- <version>0.10.28.1</version>
+ <version>0.10.28.2</version>
<license>LGPL</license>
<source>gst-plugins-good</source>
- <package>GStreamer Good Plug-ins git</package>
+ <package>GStreamer Good Plug-ins prerelease</package>
<origin>Unknown package origin</origin>
<elements>
<element>
diff --git a/docs/plugins/inspect/plugin-rtp.xml b/docs/plugins/inspect/plugin-rtp.xml
index 0d464c738..7237e17e0 100644
--- a/docs/plugins/inspect/plugin-rtp.xml
+++ b/docs/plugins/inspect/plugin-rtp.xml
@@ -3,10 +3,10 @@
<description>Real-time protocol plugins</description>
<filename>../../gst/rtp/.libs/libgstrtp.so</filename>
<basename>libgstrtp.so</basename>
- <version>0.10.28.1</version>
+ <version>0.10.28.2</version>
<license>LGPL</license>
<source>gst-plugins-good</source>
- <package>GStreamer Good Plug-ins git</package>
+ <package>GStreamer Good Plug-ins prerelease</package>
<origin>Unknown package origin</origin>
<elements>
<element>
diff --git a/docs/plugins/inspect/plugin-rtsp.xml b/docs/plugins/inspect/plugin-rtsp.xml
index 6aaa89e4c..57871fa10 100644
--- a/docs/plugins/inspect/plugin-rtsp.xml
+++ b/docs/plugins/inspect/plugin-rtsp.xml
@@ -3,10 +3,10 @@
<description>transfer data via RTSP</description>
<filename>../../gst/rtsp/.libs/libgstrtsp.so</filename>
<basename>libgstrtsp.so</basename>
- <version>0.10.28.1</version>
+ <version>0.10.28.2</version>
<license>LGPL</license>
<source>gst-plugins-good</source>
- <package>GStreamer Good Plug-ins git</package>
+ <package>GStreamer Good Plug-ins prerelease</package>
<origin>Unknown package origin</origin>
<elements>
<element>
diff --git a/docs/plugins/inspect/plugin-shapewipe.xml b/docs/plugins/inspect/plugin-shapewipe.xml
index 5b91aae21..f037351ea 100644
--- a/docs/plugins/inspect/plugin-shapewipe.xml
+++ b/docs/plugins/inspect/plugin-shapewipe.xml
@@ -3,10 +3,10 @@
<description>Shape Wipe transition filter</description>
<filename>../../gst/shapewipe/.libs/libgstshapewipe.so</filename>
<basename>libgstshapewipe.so</basename>
- <version>0.10.28.1</version>
+ <version>0.10.28.2</version>
<license>LGPL</license>
<source>gst-plugins-good</source>
- <package>GStreamer Good Plug-ins git</package>
+ <package>GStreamer Good Plug-ins prerelease</package>
<origin>Unknown package origin</origin>
<elements>
<element>
diff --git a/docs/plugins/inspect/plugin-shout2send.xml b/docs/plugins/inspect/plugin-shout2send.xml
index 21c7b419d..f2667f02e 100644
--- a/docs/plugins/inspect/plugin-shout2send.xml
+++ b/docs/plugins/inspect/plugin-shout2send.xml
@@ -3,7 +3,7 @@
<description>Sends data to an icecast server using libshout2</description>
<filename>../../ext/shout2/.libs/libgstshout2.so</filename>
<basename>libgstshout2.so</basename>
- <version>0.10.28.1</version>
+ <version>0.10.28.2</version>
<license>LGPL</license>
<source>gst-plugins-good</source>
<package>libshout2</package>
diff --git a/docs/plugins/inspect/plugin-smpte.xml b/docs/plugins/inspect/plugin-smpte.xml
index a130d29e3..28b68ec4e 100644
--- a/docs/plugins/inspect/plugin-smpte.xml
+++ b/docs/plugins/inspect/plugin-smpte.xml
@@ -3,10 +3,10 @@
<description>Apply the standard SMPTE transitions on video images</description>
<filename>../../gst/smpte/.libs/libgstsmpte.so</filename>
<basename>libgstsmpte.so</basename>
- <version>0.10.28.1</version>
+ <version>0.10.28.2</version>
<license>LGPL</license>
<source>gst-plugins-good</source>
- <package>GStreamer Good Plug-ins git</package>
+ <package>GStreamer Good Plug-ins prerelease</package>
<origin>Unknown package origin</origin>
<elements>
<element>
diff --git a/docs/plugins/inspect/plugin-soup.xml b/docs/plugins/inspect/plugin-soup.xml
index 95336c9e5..8d52447d4 100644
--- a/docs/plugins/inspect/plugin-soup.xml
+++ b/docs/plugins/inspect/plugin-soup.xml
@@ -3,10 +3,10 @@
<description>libsoup HTTP client src</description>
<filename>../../ext/soup/.libs/libgstsouphttpsrc.so</filename>
<basename>libgstsouphttpsrc.so</basename>
- <version>0.10.28.1</version>
+ <version>0.10.28.2</version>
<license>LGPL</license>
<source>gst-plugins-good</source>
- <package>GStreamer Good Plug-ins git</package>
+ <package>GStreamer Good Plug-ins prerelease</package>
<origin>Unknown package origin</origin>
<elements>
<element>
diff --git a/docs/plugins/inspect/plugin-spectrum.xml b/docs/plugins/inspect/plugin-spectrum.xml
index bd2f319d2..e069a4a40 100644
--- a/docs/plugins/inspect/plugin-spectrum.xml
+++ b/docs/plugins/inspect/plugin-spectrum.xml
@@ -3,10 +3,10 @@
<description>Run an FFT on the audio signal, output spectrum data</description>
<filename>../../gst/spectrum/.libs/libgstspectrum.so</filename>
<basename>libgstspectrum.so</basename>
- <version>0.10.28.1</version>
+ <version>0.10.28.2</version>
<license>LGPL</license>
<source>gst-plugins-good</source>
- <package>GStreamer Good Plug-ins git</package>
+ <package>GStreamer Good Plug-ins prerelease</package>
<origin>Unknown package origin</origin>
<elements>
<element>
diff --git a/docs/plugins/inspect/plugin-speex.xml b/docs/plugins/inspect/plugin-speex.xml
index b6a09e5e1..83c56cb41 100644
--- a/docs/plugins/inspect/plugin-speex.xml
+++ b/docs/plugins/inspect/plugin-speex.xml
@@ -3,10 +3,10 @@
<description>Speex plugin library</description>
<filename>../../ext/speex/.libs/libgstspeex.so</filename>
<basename>libgstspeex.so</basename>
- <version>0.10.28.1</version>
+ <version>0.10.28.2</version>
<license>LGPL</license>
<source>gst-plugins-good</source>
- <package>GStreamer Good Plug-ins git</package>
+ <package>GStreamer Good Plug-ins prerelease</package>
<origin>Unknown package origin</origin>
<elements>
<element>
diff --git a/docs/plugins/inspect/plugin-udp.xml b/docs/plugins/inspect/plugin-udp.xml
index 445c30702..bc7854cc4 100644
--- a/docs/plugins/inspect/plugin-udp.xml
+++ b/docs/plugins/inspect/plugin-udp.xml
@@ -3,10 +3,10 @@
<description>transfer data via UDP</description>
<filename>../../gst/udp/.libs/libgstudp.so</filename>
<basename>libgstudp.so</basename>
- <version>0.10.28.1</version>
+ <version>0.10.28.2</version>
<license>LGPL</license>
<source>gst-plugins-good</source>
- <package>GStreamer Good Plug-ins git</package>
+ <package>GStreamer Good Plug-ins prerelease</package>
<origin>Unknown package origin</origin>
<elements>
<element>
diff --git a/docs/plugins/inspect/plugin-video4linux2.xml b/docs/plugins/inspect/plugin-video4linux2.xml
index 8349f913d..df3adf86a 100644
--- a/docs/plugins/inspect/plugin-video4linux2.xml
+++ b/docs/plugins/inspect/plugin-video4linux2.xml
@@ -3,13 +3,37 @@
<description>elements for Video 4 Linux</description>
<filename>../../sys/v4l2/.libs/libgstvideo4linux2.so</filename>
<basename>libgstvideo4linux2.so</basename>
- <version>0.10.28.1</version>
+ <version>0.10.28.2</version>
<license>LGPL</license>
<source>gst-plugins-good</source>
- <package>GStreamer Good Plug-ins git</package>
+ <package>GStreamer Good Plug-ins prerelease</package>
<origin>Unknown package origin</origin>
<elements>
<element>
+ <name>v4l2radio</name>
+ <longname>Radio (video4linux2) Tuner</longname>
+ <class>Tuner</class>
+ <description>Controls a Video4Linux2 radio device</description>
+ <author>Alexey Chernov &lt;4ernov@gmail.com&gt;</author>
+ <pads>
+ </pads>
+ </element>
+ <element>
+ <name>v4l2sink</name>
+ <longname>Video (video4linux2) Sink</longname>
+ <class>Sink/Video</class>
+ <description>Displays frames on a video4linux2 device</description>
+ <author>Rob Clark &lt;rob@ti.com&gt;,</author>
+ <pads>
+ <caps>
+ <name>sink</name>
+ <direction>sink</direction>
+ <presence>always</presence>
+ <details>video/x-raw-rgb, bpp=(int)8, depth=(int)8, red_mask=(int)224, green_mask=(int)28, blue_mask=(int)3, endianness=(int)1234, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-raw-rgb, bpp=(int)16, depth=(int)15, red_mask=(int)31744, green_mask=(int)992, blue_mask=(int)31, endianness=(int)1234, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-raw-rgb, bpp=(int)16, depth=(int)16, red_mask=(int)63488, green_mask=(int)2016, blue_mask=(int)31, endianness=(int)1234, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-raw-rgb, bpp=(int)16, depth=(int)15, red_mask=(int)31744, green_mask=(int)992, blue_mask=(int)31, endianness=(int)4321, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-raw-rgb, bpp=(int)16, depth=(int)16, red_mask=(int)63488, green_mask=(int)2016, blue_mask=(int)31, endianness=(int)4321, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-raw-rgb, bpp=(int)24, depth=(int)24, red_mask=(int)255, green_mask=(int)65280, blue_mask=(int)16711680, endianness=(int)4321, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-raw-rgb, bpp=(int)24, depth=(int)24, red_mask=(int)16711680, green_mask=(int)65280, blue_mask=(int)255, endianness=(int)4321, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)32, red_mask=(int)255, green_mask=(int)65280, blue_mask=(int)16711680, endianness=(int)4321, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)32, red_mask=(int)-16777216, green_mask=(int)16711680, blue_mask=(int)65280, endianness=(int)4321, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-raw-gray, bpp=(int)8, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-raw-yuv, format=(fourcc)YVU9, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-raw-yuv, format=(fourcc)YV12, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-raw-yuv, format=(fourcc)YUY2, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-raw-yuv, format=(fourcc)UYVY, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-raw-yuv, format=(fourcc)Y42B, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-raw-yuv, format=(fourcc)Y41B, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-raw-yuv, format=(fourcc)Y41P, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-raw-yuv, format=(fourcc)NV12, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-raw-yuv, format=(fourcc)NV21, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-raw-yuv, format=(fourcc)YUV9, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-raw-yuv, format=(fourcc)I420, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-raw-bayer, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; image/jpeg, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; image/jpeg, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; image/jpeg, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-dv, systemstream=(boolean)true, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/mpegts; video/x-sonix, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-pwc1, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-pwc2, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-raw-yuv, format=(fourcc)YVYU, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]</details>
+ </caps>
+ </pads>
+ </element>
+ <element>
<name>v4l2src</name>
<longname>Video (video4linux2) Source</longname>
<class>Source/Video</class>
@@ -24,12 +48,5 @@
</caps>
</pads>
</element>
- <element>
- <name>v4l2radio</name>
- <longname>Radio (video4linux2) Tuner</longname>
- <class>Tuner</class>
- <description>Controls a Video4Linux2 radio device</description>
- <author>Alexey Chernov &lt;4ernov@gmail.com&gt;</author>
- </element>
</elements>
-</plugin>
+</plugin> \ No newline at end of file
diff --git a/docs/plugins/inspect/plugin-videobox.xml b/docs/plugins/inspect/plugin-videobox.xml
index 0e2651e6b..c162694b2 100644
--- a/docs/plugins/inspect/plugin-videobox.xml
+++ b/docs/plugins/inspect/plugin-videobox.xml
@@ -3,10 +3,10 @@
<description>resizes a video by adding borders or cropping</description>
<filename>../../gst/videobox/.libs/libgstvideobox.so</filename>
<basename>libgstvideobox.so</basename>
- <version>0.10.28.1</version>
+ <version>0.10.28.2</version>
<license>LGPL</license>
<source>gst-plugins-good</source>
- <package>GStreamer Good Plug-ins git</package>
+ <package>GStreamer Good Plug-ins prerelease</package>
<origin>Unknown package origin</origin>
<elements>
<element>
diff --git a/docs/plugins/inspect/plugin-videocrop.xml b/docs/plugins/inspect/plugin-videocrop.xml
index eebd7b52b..3cc94621a 100644
--- a/docs/plugins/inspect/plugin-videocrop.xml
+++ b/docs/plugins/inspect/plugin-videocrop.xml
@@ -3,10 +3,10 @@
<description>Crops video into a user-defined region</description>
<filename>../../gst/videocrop/.libs/libgstvideocrop.so</filename>
<basename>libgstvideocrop.so</basename>
- <version>0.10.28.1</version>
+ <version>0.10.28.2</version>
<license>LGPL</license>
<source>gst-plugins-good</source>
- <package>GStreamer Good Plug-ins git</package>
+ <package>GStreamer Good Plug-ins prerelease</package>
<origin>Unknown package origin</origin>
<elements>
<element>
diff --git a/docs/plugins/inspect/plugin-videofilter.xml b/docs/plugins/inspect/plugin-videofilter.xml
index c136e43dd..f792a5732 100644
--- a/docs/plugins/inspect/plugin-videofilter.xml
+++ b/docs/plugins/inspect/plugin-videofilter.xml
@@ -3,10 +3,10 @@
<description>Video filters plugin</description>
<filename>../../gst/videofilter/.libs/libgstvideofilter.so</filename>
<basename>libgstvideofilter.so</basename>
- <version>0.10.28.1</version>
+ <version>0.10.28.2</version>
<license>LGPL</license>
<source>gst-plugins-good</source>
- <package>GStreamer Good Plug-ins git</package>
+ <package>GStreamer Good Plug-ins prerelease</package>
<origin>Unknown package origin</origin>
<elements>
<element>
@@ -62,13 +62,13 @@
<name>sink</name>
<direction>sink</direction>
<presence>always</presence>
- <details>video/x-raw-yuv, format=(fourcc)AYUV, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)16711680, green_mask=(int)65280, blue_mask=(int)255, alpha_mask=(int)-16777216, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)65280, green_mask=(int)16711680, blue_mask=(int)-16777216, alpha_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)255, green_mask=(int)65280, blue_mask=(int)16711680, alpha_mask=(int)-16777216, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)-16777216, green_mask=(int)16711680, blue_mask=(int)65280, alpha_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)Y444, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)16711680, green_mask=(int)65280, blue_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)-16777216, green_mask=(int)16711680, blue_mask=(int)65280, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)255, green_mask=(int)65280, blue_mask=(int)16711680, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)65280, green_mask=(int)16711680, blue_mask=(int)-16777216, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)24, depth=(int)24, endianness=(int)4321, red_mask=(int)16711680, green_mask=(int)65280, blue_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)24, depth=(int)24, endianness=(int)4321, red_mask=(int)255, green_mask=(int)65280, blue_mask=(int)16711680, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)I420, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)YV12, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)IYUV, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]</details>
+ <details>video/x-raw-yuv, format=(fourcc)AYUV, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)16711680, green_mask=(int)65280, blue_mask=(int)255, alpha_mask=(int)-16777216, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)65280, green_mask=(int)16711680, blue_mask=(int)-16777216, alpha_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)255, green_mask=(int)65280, blue_mask=(int)16711680, alpha_mask=(int)-16777216, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)-16777216, green_mask=(int)16711680, blue_mask=(int)65280, alpha_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)Y444, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)16711680, green_mask=(int)65280, blue_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)-16777216, green_mask=(int)16711680, blue_mask=(int)65280, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)255, green_mask=(int)65280, blue_mask=(int)16711680, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)65280, green_mask=(int)16711680, blue_mask=(int)-16777216, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)24, depth=(int)24, endianness=(int)4321, red_mask=(int)16711680, green_mask=(int)65280, blue_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)24, depth=(int)24, endianness=(int)4321, red_mask=(int)255, green_mask=(int)65280, blue_mask=(int)16711680, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)I420, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)YV12, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)IYUV, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)YUY2, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)UYVY, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)YVYU, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]</details>
</caps>
<caps>
<name>src</name>
<direction>source</direction>
<presence>always</presence>
- <details>video/x-raw-yuv, format=(fourcc)AYUV, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)16711680, green_mask=(int)65280, blue_mask=(int)255, alpha_mask=(int)-16777216, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)65280, green_mask=(int)16711680, blue_mask=(int)-16777216, alpha_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)255, green_mask=(int)65280, blue_mask=(int)16711680, alpha_mask=(int)-16777216, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)-16777216, green_mask=(int)16711680, blue_mask=(int)65280, alpha_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)Y444, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)16711680, green_mask=(int)65280, blue_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)-16777216, green_mask=(int)16711680, blue_mask=(int)65280, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)255, green_mask=(int)65280, blue_mask=(int)16711680, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)65280, green_mask=(int)16711680, blue_mask=(int)-16777216, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)24, depth=(int)24, endianness=(int)4321, red_mask=(int)16711680, green_mask=(int)65280, blue_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)24, depth=(int)24, endianness=(int)4321, red_mask=(int)255, green_mask=(int)65280, blue_mask=(int)16711680, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)I420, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)YV12, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)IYUV, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]</details>
+ <details>video/x-raw-yuv, format=(fourcc)AYUV, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)16711680, green_mask=(int)65280, blue_mask=(int)255, alpha_mask=(int)-16777216, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)65280, green_mask=(int)16711680, blue_mask=(int)-16777216, alpha_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)255, green_mask=(int)65280, blue_mask=(int)16711680, alpha_mask=(int)-16777216, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)-16777216, green_mask=(int)16711680, blue_mask=(int)65280, alpha_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)Y444, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)16711680, green_mask=(int)65280, blue_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)-16777216, green_mask=(int)16711680, blue_mask=(int)65280, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)255, green_mask=(int)65280, blue_mask=(int)16711680, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)65280, green_mask=(int)16711680, blue_mask=(int)-16777216, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)24, depth=(int)24, endianness=(int)4321, red_mask=(int)16711680, green_mask=(int)65280, blue_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)24, depth=(int)24, endianness=(int)4321, red_mask=(int)255, green_mask=(int)65280, blue_mask=(int)16711680, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)I420, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)YV12, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)IYUV, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)YUY2, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)UYVY, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)YVYU, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]</details>
</caps>
</pads>
</element>
diff --git a/docs/plugins/inspect/plugin-videomixer.xml b/docs/plugins/inspect/plugin-videomixer.xml
index 3df46ca44..e71ad9b63 100644
--- a/docs/plugins/inspect/plugin-videomixer.xml
+++ b/docs/plugins/inspect/plugin-videomixer.xml
@@ -3,10 +3,10 @@
<description>Video mixer</description>
<filename>../../gst/videomixer/.libs/libgstvideomixer.so</filename>
<basename>libgstvideomixer.so</basename>
- <version>0.10.28.1</version>
+ <version>0.10.28.2</version>
<license>LGPL</license>
<source>gst-plugins-good</source>
- <package>GStreamer Good Plug-ins git</package>
+ <package>GStreamer Good Plug-ins prerelease</package>
<origin>Unknown package origin</origin>
<elements>
<element>
diff --git a/docs/plugins/inspect/plugin-wavenc.xml b/docs/plugins/inspect/plugin-wavenc.xml
index eeef9b6b4..559ca8c49 100644
--- a/docs/plugins/inspect/plugin-wavenc.xml
+++ b/docs/plugins/inspect/plugin-wavenc.xml
@@ -3,10 +3,10 @@
<description>Encode raw audio into WAV</description>
<filename>../../gst/wavenc/.libs/libgstwavenc.so</filename>
<basename>libgstwavenc.so</basename>
- <version>0.10.28.1</version>
+ <version>0.10.28.2</version>
<license>LGPL</license>
<source>gst-plugins-good</source>
- <package>GStreamer Good Plug-ins git</package>
+ <package>GStreamer Good Plug-ins prerelease</package>
<origin>Unknown package origin</origin>
<elements>
<element>
diff --git a/docs/plugins/inspect/plugin-wavpack.xml b/docs/plugins/inspect/plugin-wavpack.xml
index cd3869cdb..125552c28 100644
--- a/docs/plugins/inspect/plugin-wavpack.xml
+++ b/docs/plugins/inspect/plugin-wavpack.xml
@@ -3,10 +3,10 @@
<description>Wavpack lossless/lossy audio format handling</description>
<filename>../../ext/wavpack/.libs/libgstwavpack.so</filename>
<basename>libgstwavpack.so</basename>
- <version>0.10.28.1</version>
+ <version>0.10.28.2</version>
<license>LGPL</license>
<source>gst-plugins-good</source>
- <package>GStreamer Good Plug-ins git</package>
+ <package>GStreamer Good Plug-ins prerelease</package>
<origin>Unknown package origin</origin>
<elements>
<element>
diff --git a/docs/plugins/inspect/plugin-wavparse.xml b/docs/plugins/inspect/plugin-wavparse.xml
index 1174f2cc6..d235b9c35 100644
--- a/docs/plugins/inspect/plugin-wavparse.xml
+++ b/docs/plugins/inspect/plugin-wavparse.xml
@@ -3,10 +3,10 @@
<description>Parse a .wav file into raw audio</description>
<filename>../../gst/wavparse/.libs/libgstwavparse.so</filename>
<basename>libgstwavparse.so</basename>
- <version>0.10.28.1</version>
+ <version>0.10.28.2</version>
<license>LGPL</license>
<source>gst-plugins-good</source>
- <package>GStreamer Good Plug-ins git</package>
+ <package>GStreamer Good Plug-ins prerelease</package>
<origin>Unknown package origin</origin>
<elements>
<element>
diff --git a/docs/plugins/inspect/plugin-ximagesrc.xml b/docs/plugins/inspect/plugin-ximagesrc.xml
index f67671c9a..685940c65 100644
--- a/docs/plugins/inspect/plugin-ximagesrc.xml
+++ b/docs/plugins/inspect/plugin-ximagesrc.xml
@@ -3,10 +3,10 @@
<description>X11 video input plugin using standard Xlib calls</description>
<filename>../../sys/ximage/.libs/libgstximagesrc.so</filename>
<basename>libgstximagesrc.so</basename>
- <version>0.10.28.1</version>
+ <version>0.10.28.2</version>
<license>LGPL</license>
<source>gst-plugins-good</source>
- <package>GStreamer Good Plug-ins git</package>
+ <package>GStreamer Good Plug-ins prerelease</package>
<origin>Unknown package origin</origin>
<elements>
<element>
diff --git a/docs/plugins/inspect/plugin-y4menc.xml b/docs/plugins/inspect/plugin-y4menc.xml
index aebe07410..0fd6f2ab7 100644
--- a/docs/plugins/inspect/plugin-y4menc.xml
+++ b/docs/plugins/inspect/plugin-y4menc.xml
@@ -3,10 +3,10 @@
<description>Encodes a YUV frame into the yuv4mpeg format (mjpegtools)</description>
<filename>../../gst/y4m/.libs/libgsty4menc.so</filename>
<basename>libgsty4menc.so</basename>
- <version>0.10.28.1</version>
+ <version>0.10.28.2</version>
<license>LGPL</license>
<source>gst-plugins-good</source>
- <package>GStreamer Good Plug-ins git</package>
+ <package>GStreamer Good Plug-ins prerelease</package>
<origin>Unknown package origin</origin>
<elements>
<element>
diff --git a/ext/flac/gstflacenc.c b/ext/flac/gstflacenc.c
index a3de54333..a07fcdc0a 100644
--- a/ext/flac/gstflacenc.c
+++ b/ext/flac/gstflacenc.c
@@ -453,6 +453,13 @@ add_one_tag (const GstTagList * list, const gchar * tag, gpointer user_data)
GList *it;
GstFlacEnc *flacenc = GST_FLAC_ENC (user_data);
+ /* IMAGE and PREVIEW_IMAGE tags are already written
+ * differently, no need to store them inside the
+ * vorbiscomments too */
+ if (strcmp (tag, GST_TAG_IMAGE) == 0
+ || strcmp (tag, GST_TAG_PREVIEW_IMAGE) == 0)
+ return;
+
comments = gst_tag_to_vorbis_comments (list, tag);
for (it = comments; it != NULL; it = it->next) {
FLAC__StreamMetadata_VorbisComment_Entry commment_entry;
diff --git a/ext/jack/gstjackaudiosink.c b/ext/jack/gstjackaudiosink.c
index da1c4ac53..e9190507f 100644
--- a/ext/jack/gstjackaudiosink.c
+++ b/ext/jack/gstjackaudiosink.c
@@ -155,12 +155,8 @@ gst_jack_ring_buffer_get_type (void)
static void
gst_jack_ring_buffer_class_init (GstJackRingBufferClass * klass)
{
- GObjectClass *gobject_class;
- GstObjectClass *gstobject_class;
GstRingBufferClass *gstringbuffer_class;
- gobject_class = (GObjectClass *) klass;
- gstobject_class = (GstObjectClass *) klass;
gstringbuffer_class = (GstRingBufferClass *) klass;
ring_parent_class = g_type_class_peek_parent (klass);
@@ -188,14 +184,12 @@ jack_process_cb (jack_nframes_t nframes, void *arg)
{
GstJackAudioSink *sink;
GstRingBuffer *buf;
- GstJackRingBuffer *abuf;
gint readseg, len;
guint8 *readptr;
gint i, j, flen, channels;
sample_t **buffers, *data;
buf = GST_RING_BUFFER_CAST (arg);
- abuf = GST_JACK_RING_BUFFER_CAST (arg);
sink = GST_JACK_AUDIO_SINK (GST_OBJECT_PARENT (buf));
channels = buf->spec.channels;
@@ -588,37 +582,49 @@ gst_jack_ring_buffer_stop (GstRingBuffer * buf)
return TRUE;
}
+#if defined (HAVE_JACK_0_120_1) || defined(HAVE_JACK_1_9_7)
static guint
gst_jack_ring_buffer_delay (GstRingBuffer * buf)
{
GstJackAudioSink *sink;
guint i, res = 0;
-#ifdef HAVE_JACK_0_120_1
jack_latency_range_t range;
-#else
- guint latency;
-#endif
- jack_client_t *client;
sink = GST_JACK_AUDIO_SINK (GST_OBJECT_PARENT (buf));
- client = gst_jack_audio_client_get_client (sink->client);
for (i = 0; i < sink->port_count; i++) {
-#ifdef HAVE_JACK_0_120_1
jack_port_get_latency_range (sink->ports[i], JackPlaybackLatency, &range);
if (range.max > res)
res = range.max;
-#else
+ }
+
+ GST_LOG_OBJECT (sink, "delay %u", res);
+
+ return res;
+}
+#else /* !(defined (HAVE_JACK_0_120_1) || defined(HAVE_JACK_1_9_7)) */
+static guint
+gst_jack_ring_buffer_delay (GstRingBuffer * buf)
+{
+ GstJackAudioSink *sink;
+ guint i, res = 0;
+ guint latency;
+ jack_client_t *client;
+
+ sink = GST_JACK_AUDIO_SINK (GST_OBJECT_PARENT (buf));
+ client = gst_jack_audio_client_get_client (sink->client);
+
+ for (i = 0; i < sink->port_count; i++) {
latency = jack_port_get_total_latency (client, sink->ports[i]);
if (latency > res)
res = latency;
-#endif
}
GST_LOG_OBJECT (sink, "delay %u", res);
return res;
}
+#endif
static GstStaticPadTemplate jackaudiosink_sink_factory =
GST_STATIC_PAD_TEMPLATE ("sink",
@@ -682,12 +688,10 @@ static void
gst_jack_audio_sink_class_init (GstJackAudioSinkClass * klass)
{
GObjectClass *gobject_class;
- GstElementClass *gstelement_class;
GstBaseSinkClass *gstbasesink_class;
GstBaseAudioSinkClass *gstbaseaudiosink_class;
gobject_class = (GObjectClass *) klass;
- gstelement_class = (GstElementClass *) klass;
gstbasesink_class = (GstBaseSinkClass *) klass;
gstbaseaudiosink_class = (GstBaseAudioSinkClass *) klass;
diff --git a/ext/jack/gstjackaudiosrc.c b/ext/jack/gstjackaudiosrc.c
index 68d11f85a..d5a8733b1 100644
--- a/ext/jack/gstjackaudiosrc.c
+++ b/ext/jack/gstjackaudiosrc.c
@@ -176,12 +176,8 @@ gst_jack_ring_buffer_get_type (void)
static void
gst_jack_ring_buffer_class_init (GstJackRingBufferClass * klass)
{
- GObjectClass *gobject_class;
- GstObjectClass *gstobject_class;
GstRingBufferClass *gstringbuffer_class;
- gobject_class = (GObjectClass *) klass;
- gstobject_class = (GstObjectClass *) klass;
gstringbuffer_class = (GstRingBufferClass *) klass;
ring_parent_class = g_type_class_peek_parent (klass);
@@ -599,37 +595,50 @@ gst_jack_ring_buffer_stop (GstRingBuffer * buf)
return TRUE;
}
+#if defined (HAVE_JACK_0_120_1) || defined(HAVE_JACK_1_9_7)
static guint
gst_jack_ring_buffer_delay (GstRingBuffer * buf)
{
GstJackAudioSrc *src;
guint i, res = 0;
-#ifdef HAVE_JACK_0_120_1
jack_latency_range_t range;
-#else
- guint latency;
-#endif
- jack_client_t *client;
src = GST_JACK_AUDIO_SRC (GST_OBJECT_PARENT (buf));
- client = gst_jack_audio_client_get_client (src->client);
for (i = 0; i < src->port_count; i++) {
-#ifdef HAVE_JACK_0_120_1
jack_port_get_latency_range (src->ports[i], JackCaptureLatency, &range);
if (range.max > res)
res = range.max;
-#else
+ }
+
+ GST_DEBUG_OBJECT (src, "delay %u", res);
+
+ return res;
+}
+#else /* !(defined (HAVE_JACK_0_120_1) || defined(HAVE_JACK_1_9_7)) */
+static guint
+gst_jack_ring_buffer_delay (GstRingBuffer * buf)
+{
+ GstJackAudioSrc *src;
+ guint i, res = 0;
+ guint latency;
+ jack_client_t *client;
+
+ src = GST_JACK_AUDIO_SRC (GST_OBJECT_PARENT (buf));
+
+ client = gst_jack_audio_client_get_client (src->client);
+
+ for (i = 0; i < src->port_count; i++) {
latency = jack_port_get_total_latency (client, src->ports[i]);
if (latency > res)
res = latency;
-#endif
}
GST_DEBUG_OBJECT (src, "delay %u", res);
return res;
}
+#endif
/* Audiosrc signals and args */
enum
@@ -700,12 +709,10 @@ static void
gst_jack_audio_src_class_init (GstJackAudioSrcClass * klass)
{
GObjectClass *gobject_class;
- GstElementClass *gstelement_class;
GstBaseSrcClass *gstbasesrc_class;
GstBaseAudioSrcClass *gstbaseaudiosrc_class;
gobject_class = (GObjectClass *) klass;
- gstelement_class = (GstElementClass *) klass;
gstbasesrc_class = (GstBaseSrcClass *) klass;
gstbaseaudiosrc_class = (GstBaseAudioSrcClass *) klass;
diff --git a/ext/jpeg/gstjpegdec.c b/ext/jpeg/gstjpegdec.c
index c2189cc08..99547fcb4 100644
--- a/ext/jpeg/gstjpegdec.c
+++ b/ext/jpeg/gstjpegdec.c
@@ -1651,6 +1651,10 @@ gst_jpeg_dec_src_event (GstPad * pad, GstEvent * event)
gboolean res;
dec = GST_JPEG_DEC (gst_pad_get_parent (pad));
+ if (G_UNLIKELY (dec == NULL)) {
+ gst_event_unref (event);
+ return FALSE;
+ }
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_QOS:{
diff --git a/ext/jpeg/gstjpegenc.c b/ext/jpeg/gstjpegenc.c
index 60e2e99bb..8708a70a4 100644
--- a/ext/jpeg/gstjpegenc.c
+++ b/ext/jpeg/gstjpegenc.c
@@ -547,7 +547,7 @@ gst_jpegenc_chain (GstPad * pad, GstBuffer * buf)
GstJpegEnc *jpegenc;
guchar *data;
gulong size;
- guint height, width;
+ guint height;
guchar *base[3], *end[3];
gint i, j, k;
@@ -572,7 +572,6 @@ gst_jpegenc_chain (GstPad * pad, GstBuffer * buf)
gst_buffer_copy_metadata (jpegenc->output_buffer, buf,
GST_BUFFER_COPY_TIMESTAMPS);
- width = jpegenc->width;
height = jpegenc->height;
for (i = 0; i < jpegenc->channels; i++) {
diff --git a/ext/pulse/pulsesink.c b/ext/pulse/pulsesink.c
index d93e5c890..e4fe6e36d 100644
--- a/ext/pulse/pulsesink.c
+++ b/ext/pulse/pulsesink.c
@@ -941,10 +941,8 @@ connect_failed:
static gboolean
gst_pulseringbuffer_release (GstRingBuffer * buf)
{
- GstPulseSink *psink;
GstPulseRingBuffer *pbuf;
- psink = GST_PULSESINK_CAST (GST_OBJECT_PARENT (buf));
pbuf = GST_PULSERING_BUFFER_CAST (buf);
pa_threaded_mainloop_lock (mainloop);
@@ -957,12 +955,6 @@ gst_pulseringbuffer_release (GstRingBuffer * buf)
static void
gst_pulsering_success_cb (pa_stream * s, int success, void *userdata)
{
- GstPulseRingBuffer *pbuf;
- GstPulseSink *psink;
-
- pbuf = GST_PULSERING_BUFFER_CAST (userdata);
- psink = GST_PULSESINK_CAST (GST_OBJECT_PARENT (pbuf));
-
pa_threaded_mainloop_signal (mainloop, 0);
}
@@ -1080,8 +1072,8 @@ gst_pulseringbuffer_start (GstRingBuffer * buf)
/* EOS needs running clock */
if (GST_BASE_SINK_CAST (psink)->eos ||
- g_atomic_int_get (&GST_BASE_AUDIO_SINK (psink)->abidata.
- ABI.eos_rendering))
+ g_atomic_int_get (&GST_BASE_AUDIO_SINK (psink)->abidata.ABI.
+ eos_rendering))
gst_pulsering_set_corked (pbuf, FALSE, FALSE);
pa_threaded_mainloop_unlock (mainloop);
@@ -1351,11 +1343,11 @@ gst_pulseringbuffer_commit (GstRingBuffer * buf, guint64 * sample,
towrite = out_samples * bps;
- /* Only ever write bufsize bytes at once. This will
- * also limit the PA shm buffer to bufsize
+ /* Only ever write segsize bytes at once. This will
+ * also limit the PA shm buffer to segsize
*/
- if (towrite > bufsize)
- towrite = bufsize;
+ if (towrite > buf->spec.segsize)
+ towrite = buf->spec.segsize;
if ((pbuf->m_writable < towrite) || (offset != pbuf->m_lastoffset)) {
/* if no room left or discontinuity in offset,
@@ -1404,9 +1396,9 @@ gst_pulseringbuffer_commit (GstRingBuffer * buf, guint64 * sample,
}
/* make sure we only buffer up latency-time samples */
- if (pbuf->m_writable > bufsize) {
+ if (pbuf->m_writable > buf->spec.segsize) {
/* limit buffering to latency-time value */
- pbuf->m_writable = bufsize;
+ pbuf->m_writable = buf->spec.segsize;
GST_LOG_OBJECT (psink, "Limiting buffering to %" G_GSIZE_FORMAT,
pbuf->m_writable);
@@ -1425,9 +1417,9 @@ gst_pulseringbuffer_commit (GstRingBuffer * buf, guint64 * sample,
pbuf->m_writable);
/* Just to make sure that we didn't get more than requested */
- if (pbuf->m_writable > bufsize) {
+ if (pbuf->m_writable > buf->spec.segsize) {
/* limit buffering to latency-time value */
- pbuf->m_writable = bufsize;
+ pbuf->m_writable = buf->spec.segsize;
}
}
@@ -2730,7 +2722,6 @@ gst_pulsesink_change_state (GstElement * element, GstStateChange transition)
{
GstPulseSink *pulsesink = GST_PULSESINK (element);
GstStateChangeReturn ret;
- guint res;
switch (transition) {
case GST_STATE_CHANGE_NULL_TO_READY:
@@ -2740,8 +2731,7 @@ gst_pulsesink_change_state (GstElement * element, GstStateChange transition)
if (!(mainloop = pa_threaded_mainloop_new ()))
goto mainloop_failed;
mainloop_ref_ct = 1;
- res = pa_threaded_mainloop_start (mainloop);
- g_assert (res == 0);
+ pa_threaded_mainloop_start (mainloop);
g_mutex_unlock (pa_shared_resource_mutex);
} else {
GST_INFO_OBJECT (element, "reusing pa main loop thread");
diff --git a/ext/pulse/pulsesrc.c b/ext/pulse/pulsesrc.c
index 06fb2069c..504a1293b 100644
--- a/ext/pulse/pulsesrc.c
+++ b/ext/pulse/pulsesrc.c
@@ -1250,15 +1250,13 @@ gst_pulsesrc_change_state (GstElement * element, GstStateChange transition)
{
GstStateChangeReturn ret;
GstPulseSrc *this = GST_PULSESRC_CAST (element);
- int e;
switch (transition) {
case GST_STATE_CHANGE_NULL_TO_READY:
this->mainloop = pa_threaded_mainloop_new ();
g_assert (this->mainloop);
- e = pa_threaded_mainloop_start (this->mainloop);
- g_assert (e == 0);
+ pa_threaded_mainloop_start (this->mainloop);
if (!this->mixer)
this->mixer =
diff --git a/ext/raw1394/gstdv1394src.c b/ext/raw1394/gstdv1394src.c
index 16c4326a1..a175b6201 100644
--- a/ext/raw1394/gstdv1394src.c
+++ b/ext/raw1394/gstdv1394src.c
@@ -66,7 +66,7 @@
#define SEND_COMMAND(src, command) \
G_STMT_START { \
- int _res; unsigned char c; c = command; \
+ int G_GNUC_UNUSED _res; unsigned char c; c = command; \
_res = write (WRITE_SOCKET(src), &c, 1); \
} G_STMT_END
diff --git a/ext/raw1394/gsthdv1394src.c b/ext/raw1394/gsthdv1394src.c
index d701afba3..70b602bf6 100644
--- a/ext/raw1394/gsthdv1394src.c
+++ b/ext/raw1394/gsthdv1394src.c
@@ -62,7 +62,7 @@
#define SEND_COMMAND(src, command) \
G_STMT_START { \
- int _res; unsigned char c; c = command; \
+ int G_GNUC_UNUSED _res; unsigned char c; c = command; \
_res = write (WRITE_SOCKET(src), &c, 1); \
} G_STMT_END
diff --git a/ext/speex/gstspeexenc.c b/ext/speex/gstspeexenc.c
index 4a0bba614..6ace2da12 100644
--- a/ext/speex/gstspeexenc.c
+++ b/ext/speex/gstspeexenc.c
@@ -901,7 +901,7 @@ gst_speex_enc_encode (GstSpeexEnc * enc, gboolean flush)
while (gst_adapter_available (enc->adapter) >= bytes) {
gint16 *data;
- gint outsize, written;
+ gint outsize, written, dtx_ret;
GstBuffer *outbuf;
data = (gint16 *) gst_adapter_take (enc->adapter, bytes);
@@ -913,7 +913,7 @@ gst_speex_enc_encode (GstSpeexEnc * enc, gboolean flush)
if (enc->channels == 2) {
speex_encode_stereo_int (data, frame_size, &enc->bits);
}
- speex_encode_int (enc->state, data, &enc->bits);
+ dtx_ret = speex_encode_int (enc->state, data, &enc->bits);
g_free (data);
@@ -934,9 +934,17 @@ gst_speex_enc_encode (GstSpeexEnc * enc, gboolean flush)
written = speex_bits_write (&enc->bits,
(gchar *) GST_BUFFER_DATA (outbuf), outsize);
- g_assert (written == outsize);
+
+ if (G_UNLIKELY (written != outsize)) {
+ GST_ERROR_OBJECT (enc, "short write: %d < %d bytes", written, outsize);
+ GST_BUFFER_SIZE (outbuf) = written;
+ }
+
speex_bits_reset (&enc->bits);
+ if (!dtx_ret)
+ GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_GAP);
+
GST_BUFFER_TIMESTAMP (outbuf) = enc->start_ts +
gst_util_uint64_scale_int ((enc->frameno_out -
enc->nframes) * frame_size - enc->lookahead, GST_SECOND, enc->rate);
diff --git a/gst-plugins-good.spec.in b/gst-plugins-good.spec.in
index 88dc858ac..e2c0f64ea 100644
--- a/gst-plugins-good.spec.in
+++ b/gst-plugins-good.spec.in
@@ -139,6 +139,7 @@ rm -rf $RPM_BUILD_ROOT
%{_libdir}/gstreamer-%{majorminor}/libgstimagefreeze.so
%{_libdir}/gstreamer-%{majorminor}/libgstshapewipe.so
%{_libdir}/gstreamer-%{majorminor}/libgstvideofilter.so
+%{_libdir}/gstreamer-%{majorminor}/libgstaudioparsers.so
# sys plugins
@USE_GST_V4L2_TRUE@%{_libdir}/gstreamer-%{majorminor}/libgstvideo4linux2.so
diff --git a/gst/alpha/Makefile.am b/gst/alpha/Makefile.am
index e225f27bb..dcd88ae04 100644
--- a/gst/alpha/Makefile.am
+++ b/gst/alpha/Makefile.am
@@ -17,3 +17,17 @@ libgstalphacolor_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
libgstalphacolor_la_LIBTOOLFLAGS = --tag=disable-static
noinst_HEADERS = gstalpha.h gstalphacolor.h
+
+Android.mk: Makefile.am $(BUILT_SOURCES)
+ androgenizer \
+ -:PROJECT libgstalpha -:SHARED libgstalpha \
+ -:TAGS eng debug \
+ -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
+ -:SOURCES $(libgstalpha_la_SOURCES) \
+ -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstalpha_la_CFLAGS) \
+ -:LDFLAGS $(libgstalpha_la_LDFLAGS) \
+ $(libgstalpha_la_LIBADD) \
+ -ldl \
+ -:PASSTHROUGH LOCAL_ARM_MODE:=arm \
+ LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \
+ > $@
diff --git a/gst/apetag/Makefile.am b/gst/apetag/Makefile.am
index b391f5eaf..54950f285 100644
--- a/gst/apetag/Makefile.am
+++ b/gst/apetag/Makefile.am
@@ -14,3 +14,17 @@ libgstapetag_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
libgstapetag_la_LIBTOOLFLAGS = --tag=disable-static
noinst_HEADERS = gstapedemux.h
+
+Android.mk: Makefile.am $(BUILT_SOURCES)
+ androgenizer \
+ -:PROJECT libgstapetag -:SHARED libgstapetag \
+ -:TAGS eng debug \
+ -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
+ -:SOURCES $(libgstapetag_la_SOURCES) \
+ -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstapetag_la_CFLAGS) \
+ -:LDFLAGS $(libgstapetag_la_LDFLAGS) \
+ $(libgstapetag_la_LIBADD) \
+ -ldl \
+ -:PASSTHROUGH LOCAL_ARM_MODE:=arm \
+ LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \
+ > $@
diff --git a/gst/audiofx/Makefile.am b/gst/audiofx/Makefile.am
index bd66963a7..c943e20f2 100644
--- a/gst/audiofx/Makefile.am
+++ b/gst/audiofx/Makefile.am
@@ -51,3 +51,16 @@ noinst_HEADERS = audiopanorama.h \
audioecho.h \
math_compat.h
+Android.mk: Makefile.am $(BUILT_SOURCES)
+ androgenizer \
+ -:PROJECT libgstaudiofx -:SHARED libgstaudiofx \
+ -:TAGS eng debug \
+ -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
+ -:SOURCES $(libgstaudiofx_la_SOURCES) \
+ -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstaudiofx_la_CFLAGS) \
+ -:LDFLAGS $(libgstaudiofx_la_LDFLAGS) \
+ $(libgstaudiofx_la_LIBADD) \
+ -ldl \
+ -:PASSTHROUGH LOCAL_ARM_MODE:=arm \
+ LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \
+ > $@
diff --git a/gst/audiofx/audiowsincband.c b/gst/audiofx/audiowsincband.c
index c6e2a0d1a..07356e240 100644
--- a/gst/audiofx/audiowsincband.c
+++ b/gst/audiofx/audiowsincband.c
@@ -26,6 +26,8 @@
* chapter 16
* available at http://www.dspguide.com/
*
+ * For the window functions see
+ * http://en.wikipedia.org/wiki/Window_function
*/
/**
@@ -104,7 +106,10 @@ gst_gst_audio_wsincband_mode_get_type (void)
enum
{
WINDOW_HAMMING = 0,
- WINDOW_BLACKMAN
+ WINDOW_BLACKMAN,
+ WINDOW_GAUSSIAN,
+ WINDOW_COSINE,
+ WINDOW_HANN
};
#define GST_TYPE_AUDIO_WSINC_BAND_WINDOW (gst_gst_audio_wsincband_window_get_type ())
@@ -119,6 +124,12 @@ gst_gst_audio_wsincband_window_get_type (void)
"hamming"},
{WINDOW_BLACKMAN, "Blackman window",
"blackman"},
+ {WINDOW_GAUSSIAN, "Gaussian window",
+ "gaussian"},
+ {WINDOW_COSINE, "Cosine window",
+ "cosine"},
+ {WINDOW_HANN, "Hann window",
+ "hann"},
{0, NULL, NULL}
};
@@ -143,6 +154,9 @@ static void gst_audio_wsincband_finalize (GObject * object);
static gboolean gst_audio_wsincband_setup (GstAudioFilter * base,
GstRingBufferSpec * format);
+
+#define POW2(x) (x)*(x)
+
/* Element class */
static void
gst_audio_wsincband_base_init (gpointer g_class)
@@ -258,18 +272,30 @@ gst_audio_wsincband_build_kernel (GstAudioWSincBand * self)
w = 2 * G_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)
+ if (i == (len - 1) / 2.0)
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 * G_PI * i / len));
- else
- kernel_lp[i] *=
- (0.42 - 0.5 * cos (2 * G_PI * i / len) +
- 0.08 * cos (4 * G_PI * i / len));
+ kernel_lp[i] = sin (w * (i - (len - 1) / 2.0)) / (i - (len - 1) / 2.0);
+
+ /* windowing */
+ switch (self->window) {
+ case WINDOW_HAMMING:
+ kernel_lp[i] *= (0.54 - 0.46 * cos (2 * G_PI * i / (len - 1)));
+ break;
+ case WINDOW_BLACKMAN:
+ kernel_lp[i] *= (0.42 - 0.5 * cos (2 * G_PI * i / (len - 1)) +
+ 0.08 * cos (4 * G_PI * i / (len - 1)));
+ break;
+ case WINDOW_GAUSSIAN:
+ kernel_lp[i] *= exp (-0.5 * POW2 (3.0 / len * (2 * i - (len - 1))));
+ break;
+ case WINDOW_COSINE:
+ kernel_lp[i] *= cos (G_PI * i / (len - 1) - G_PI / 2);
+ break;
+ case WINDOW_HANN:
+ kernel_lp[i] *= 0.5 * (1 - cos (2 * G_PI * i / (len - 1)));
+ break;
+ }
}
/* normalize for unity gain at DC */
@@ -283,18 +309,30 @@ gst_audio_wsincband_build_kernel (GstAudioWSincBand * self)
w = 2 * G_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)
+ if (i == (len - 1) / 2.0)
kernel_hp[i] = w;
else
- kernel_hp[i] = sin (w * (i - len / 2))
- / (i - len / 2);
+ kernel_hp[i] = sin (w * (i - (len - 1) / 2.0)) / (i - (len - 1) / 2.0);
+
/* Windowing */
- if (self->window == WINDOW_HAMMING)
- kernel_hp[i] *= (0.54 - 0.46 * cos (2 * G_PI * i / len));
- else
- kernel_hp[i] *=
- (0.42 - 0.5 * cos (2 * G_PI * i / len) +
- 0.08 * cos (4 * G_PI * i / len));
+ switch (self->window) {
+ case WINDOW_HAMMING:
+ kernel_hp[i] *= (0.54 - 0.46 * cos (2 * G_PI * i / (len - 1)));
+ break;
+ case WINDOW_BLACKMAN:
+ kernel_hp[i] *= (0.42 - 0.5 * cos (2 * G_PI * i / (len - 1)) +
+ 0.08 * cos (4 * G_PI * i / (len - 1)));
+ break;
+ case WINDOW_GAUSSIAN:
+ kernel_hp[i] *= exp (-0.5 * POW2 (3.0 / len * (2 * i - (len - 1))));
+ break;
+ case WINDOW_COSINE:
+ kernel_hp[i] *= cos (G_PI * i / (len - 1) - G_PI / 2);
+ break;
+ case WINDOW_HANN:
+ kernel_hp[i] *= 0.5 * (1 - cos (2 * G_PI * i / (len - 1)));
+ break;
+ }
}
/* normalize for unity gain at DC */
@@ -307,7 +345,12 @@ gst_audio_wsincband_build_kernel (GstAudioWSincBand * self)
/* 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;
+ if (len % 2 == 1) {
+ kernel_hp[(len - 1) / 2] += 1.0;
+ } else {
+ kernel_hp[len / 2 - 1] += 0.5;
+ kernel_hp[len / 2] += 0.5;
+ }
/* combine the two kernels */
kernel = g_new (gdouble, len);
diff --git a/gst/audiofx/audiowsinclimit.c b/gst/audiofx/audiowsinclimit.c
index 046f1ca26..aa0cf4b0f 100644
--- a/gst/audiofx/audiowsinclimit.c
+++ b/gst/audiofx/audiowsinclimit.c
@@ -26,6 +26,8 @@
* chapter 16
* available at http://www.dspguide.com/
*
+ * For the window functions see
+ * http://en.wikipedia.org/wiki/Window_function
*/
/**
@@ -103,7 +105,10 @@ gst_audio_wsinclimit_mode_get_type (void)
enum
{
WINDOW_HAMMING = 0,
- WINDOW_BLACKMAN
+ WINDOW_BLACKMAN,
+ WINDOW_GAUSSIAN,
+ WINDOW_COSINE,
+ WINDOW_HANN
};
#define GST_TYPE_AUDIO_WSINC_LIMIT_WINDOW (gst_audio_wsinclimit_window_get_type ())
@@ -118,6 +123,12 @@ gst_audio_wsinclimit_window_get_type (void)
"hamming"},
{WINDOW_BLACKMAN, "Blackman window",
"blackman"},
+ {WINDOW_GAUSSIAN, "Gaussian window",
+ "gaussian"},
+ {WINDOW_COSINE, "Cosine window",
+ "cosine"},
+ {WINDOW_HANN, "Hann window",
+ "hann"},
{0, NULL, NULL}
};
@@ -142,6 +153,9 @@ static void gst_audio_wsinclimit_finalize (GObject * object);
static gboolean gst_audio_wsinclimit_setup (GstAudioFilter * base,
GstRingBufferSpec * format);
+
+#define POW2(x) (x)*(x)
+
/* Element class */
static void
@@ -244,16 +258,30 @@ gst_audio_wsinclimit_build_kernel (GstAudioWSincLimit * self)
kernel = g_new (gdouble, len);
for (i = 0; i < len; ++i) {
- if (i == len / 2)
+ if (i == (len - 1) / 2.0)
kernel[i] = w;
else
- kernel[i] = sin (w * (i - len / 2)) / (i - len / 2);
+ kernel[i] = sin (w * (i - (len - 1) / 2)) / (i - (len - 1) / 2.0);
+
/* windowing */
- if (self->window == WINDOW_HAMMING)
- kernel[i] *= (0.54 - 0.46 * cos (2 * G_PI * i / len));
- else
- kernel[i] *= (0.42 - 0.5 * cos (2 * G_PI * i / len) +
- 0.08 * cos (4 * G_PI * i / len));
+ switch (self->window) {
+ case WINDOW_HAMMING:
+ kernel[i] *= (0.54 - 0.46 * cos (2 * G_PI * i / (len - 1)));
+ break;
+ case WINDOW_BLACKMAN:
+ kernel[i] *= (0.42 - 0.5 * cos (2 * G_PI * i / (len - 1)) +
+ 0.08 * cos (4 * G_PI * i / (len - 1)));
+ break;
+ case WINDOW_GAUSSIAN:
+ kernel[i] *= exp (-0.5 * POW2 (3.0 / len * (2 * i - (len - 1))));
+ break;
+ case WINDOW_COSINE:
+ kernel[i] *= cos (G_PI * i / (len - 1) - G_PI / 2);
+ break;
+ case WINDOW_HANN:
+ kernel[i] *= 0.5 * (1 - cos (2 * G_PI * i / (len - 1)));
+ break;
+ }
}
/* normalize for unity gain at DC */
@@ -266,7 +294,13 @@ gst_audio_wsinclimit_build_kernel (GstAudioWSincLimit * self)
if (self->mode == MODE_HIGH_PASS) {
for (i = 0; i < len; ++i)
kernel[i] = -kernel[i];
- kernel[len / 2] += 1.0;
+
+ if (len % 2 == 1) {
+ kernel[(len - 1) / 2] += 1.0;
+ } else {
+ kernel[len / 2 - 1] += 0.5;
+ kernel[len / 2] += 0.5;
+ }
}
gst_audio_fx_base_fir_filter_set_kernel (GST_AUDIO_FX_BASE_FIR_FILTER (self),
diff --git a/gst/audioparsers/Makefile.am b/gst/audioparsers/Makefile.am
new file mode 100644
index 000000000..22bc81fa0
--- /dev/null
+++ b/gst/audioparsers/Makefile.am
@@ -0,0 +1,18 @@
+plugin_LTLIBRARIES = libgstaudioparsers.la
+
+libgstaudioparsers_la_SOURCES = \
+ gstaacparse.c gstamrparse.c gstac3parse.c \
+ gstdcaparse.c gstflacparse.c gstmpegaudioparse.c \
+ plugin.c
+
+libgstaudioparsers_la_CFLAGS = \
+ $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS)
+libgstaudioparsers_la_LIBADD = \
+ $(GST_PLUGINS_BASE_LIBS) -lgsttag-$(GST_MAJORMINOR) \
+ -lgstaudio-$(GST_MAJORMINOR) \
+ $(GST_BASE_LIBS) $(GST_LIBS)
+libgstaudioparsers_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
+libgstaudioparsers_la_LIBTOOLFLAGS = --tag=disable-static
+
+noinst_HEADERS = gstaacparse.h gstamrparse.h gstac3parse.h \
+ gstdcaparse.h gstflacparse.h gstmpegaudioparse.h
diff --git a/gst/audioparsers/gstaacparse.c b/gst/audioparsers/gstaacparse.c
new file mode 100644
index 000000000..df7c401ab
--- /dev/null
+++ b/gst/audioparsers/gstaacparse.c
@@ -0,0 +1,717 @@
+/* GStreamer AAC parser plugin
+ * Copyright (C) 2008 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Stefan Kost <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-aacparse
+ * @short_description: AAC parser
+ * @see_also: #GstAmrParse
+ *
+ * This is an AAC parser which handles both ADIF and ADTS stream formats.
+ *
+ * As ADIF format is not framed, it is not seekable and stream duration cannot
+ * be determined either. However, ADTS format AAC clips can be seeked, and parser
+ * can also estimate playback position and clip duration.
+ *
+ * <refsect2>
+ * <title>Example launch line</title>
+ * |[
+ * gst-launch filesrc location=abc.aac ! aacparse ! faad ! audioresample ! audioconvert ! alsasink
+ * ]|
+ * </refsect2>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+
+#include "gstaacparse.h"
+
+
+static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS ("audio/mpeg, "
+ "framed = (boolean) true, " "mpegversion = (int) { 2, 4 }, "
+ "stream-format = (string) { raw, adts, adif };"));
+
+static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS ("audio/mpeg, "
+ "framed = (boolean) false, " "mpegversion = (int) { 2, 4 };"));
+
+GST_DEBUG_CATEGORY_STATIC (aacparse_debug);
+#define GST_CAT_DEFAULT aacparse_debug
+
+
+#define ADIF_MAX_SIZE 40 /* Should be enough */
+#define ADTS_MAX_SIZE 10 /* Should be enough */
+
+
+#define AAC_FRAME_DURATION(parse) (GST_SECOND/parse->frames_per_sec)
+
+gboolean gst_aac_parse_start (GstBaseParse * parse);
+gboolean gst_aac_parse_stop (GstBaseParse * parse);
+
+static gboolean gst_aac_parse_sink_setcaps (GstBaseParse * parse,
+ GstCaps * caps);
+
+gboolean gst_aac_parse_check_valid_frame (GstBaseParse * parse,
+ GstBaseParseFrame * frame, guint * size, gint * skipsize);
+
+GstFlowReturn gst_aac_parse_parse_frame (GstBaseParse * parse,
+ GstBaseParseFrame * frame);
+
+gboolean gst_aac_parse_convert (GstBaseParse * parse,
+ GstFormat src_format,
+ gint64 src_value, GstFormat dest_format, gint64 * dest_value);
+
+gint gst_aac_parse_get_frame_overhead (GstBaseParse * parse,
+ GstBuffer * buffer);
+
+gboolean gst_aac_parse_event (GstBaseParse * parse, GstEvent * event);
+
+#define _do_init(bla) \
+ GST_DEBUG_CATEGORY_INIT (aacparse_debug, "aacparse", 0, \
+ "AAC audio stream parser");
+
+GST_BOILERPLATE_FULL (GstAacParse, gst_aac_parse, GstBaseParse,
+ GST_TYPE_BASE_PARSE, _do_init);
+
+static inline gint
+gst_aac_parse_get_sample_rate_from_index (guint sr_idx)
+{
+ static const guint aac_sample_rates[] = { 96000, 88200, 64000, 48000, 44100,
+ 32000, 24000, 22050, 16000, 12000, 11025, 8000
+ };
+
+ if (sr_idx < G_N_ELEMENTS (aac_sample_rates))
+ return aac_sample_rates[sr_idx];
+ GST_WARNING ("Invalid sample rate index %u", sr_idx);
+ return 0;
+}
+
+/**
+ * gst_aac_parse_base_init:
+ * @klass: #GstElementClass.
+ *
+ */
+static void
+gst_aac_parse_base_init (gpointer klass)
+{
+ GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+
+ 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,
+ "AAC audio stream parser", "Codec/Parser/Audio",
+ "Advanced Audio Coding parser", "Stefan Kost <stefan.kost@nokia.com>");
+}
+
+
+/**
+ * gst_aac_parse_class_init:
+ * @klass: #GstAacParseClass.
+ *
+ */
+static void
+gst_aac_parse_class_init (GstAacParseClass * klass)
+{
+ GstBaseParseClass *parse_class = GST_BASE_PARSE_CLASS (klass);
+
+ parse_class->start = GST_DEBUG_FUNCPTR (gst_aac_parse_start);
+ parse_class->stop = GST_DEBUG_FUNCPTR (gst_aac_parse_stop);
+ parse_class->set_sink_caps = GST_DEBUG_FUNCPTR (gst_aac_parse_sink_setcaps);
+ parse_class->parse_frame = GST_DEBUG_FUNCPTR (gst_aac_parse_parse_frame);
+ parse_class->check_valid_frame =
+ GST_DEBUG_FUNCPTR (gst_aac_parse_check_valid_frame);
+}
+
+
+/**
+ * gst_aac_parse_init:
+ * @aacparse: #GstAacParse.
+ * @klass: #GstAacParseClass.
+ *
+ */
+static void
+gst_aac_parse_init (GstAacParse * aacparse, GstAacParseClass * klass)
+{
+ GST_DEBUG ("initialized");
+}
+
+
+/**
+ * gst_aac_parse_set_src_caps:
+ * @aacparse: #GstAacParse.
+ * @sink_caps: (proposed) caps of sink pad
+ *
+ * Set source pad caps according to current knowledge about the
+ * audio stream.
+ *
+ * Returns: TRUE if caps were successfully set.
+ */
+static gboolean
+gst_aac_parse_set_src_caps (GstAacParse * aacparse, GstCaps * sink_caps)
+{
+ GstStructure *s;
+ GstCaps *src_caps = NULL;
+ gboolean res = FALSE;
+ const gchar *stream_format;
+
+ GST_DEBUG_OBJECT (aacparse, "sink caps: %" GST_PTR_FORMAT, sink_caps);
+ if (sink_caps)
+ src_caps = gst_caps_copy (sink_caps);
+ else
+ src_caps = gst_caps_new_simple ("audio/mpeg", NULL);
+
+ gst_caps_set_simple (src_caps, "framed", G_TYPE_BOOLEAN, TRUE,
+ "mpegversion", G_TYPE_INT, aacparse->mpegversion, NULL);
+
+ switch (aacparse->header_type) {
+ case DSPAAC_HEADER_NONE:
+ stream_format = "raw";
+ break;
+ case DSPAAC_HEADER_ADTS:
+ stream_format = "adts";
+ break;
+ case DSPAAC_HEADER_ADIF:
+ stream_format = "adif";
+ break;
+ default:
+ stream_format = NULL;
+ }
+
+ s = gst_caps_get_structure (src_caps, 0);
+ if (aacparse->sample_rate > 0)
+ gst_structure_set (s, "rate", G_TYPE_INT, aacparse->sample_rate, NULL);
+ if (aacparse->channels > 0)
+ gst_structure_set (s, "channels", G_TYPE_INT, aacparse->channels, NULL);
+ if (stream_format)
+ gst_structure_set (s, "stream-format", G_TYPE_STRING, stream_format, NULL);
+
+ GST_DEBUG_OBJECT (aacparse, "setting src caps: %" GST_PTR_FORMAT, src_caps);
+
+ res = gst_pad_set_caps (GST_BASE_PARSE (aacparse)->srcpad, src_caps);
+ gst_caps_unref (src_caps);
+ return res;
+}
+
+
+/**
+ * gst_aac_parse_sink_setcaps:
+ * @sinkpad: GstPad
+ * @caps: GstCaps
+ *
+ * Implementation of "set_sink_caps" vmethod in #GstBaseParse class.
+ *
+ * Returns: TRUE on success.
+ */
+static gboolean
+gst_aac_parse_sink_setcaps (GstBaseParse * parse, GstCaps * caps)
+{
+ GstAacParse *aacparse;
+ GstStructure *structure;
+ gchar *caps_str;
+ const GValue *value;
+
+ aacparse = GST_AAC_PARSE (parse);
+ structure = gst_caps_get_structure (caps, 0);
+ caps_str = gst_caps_to_string (caps);
+
+ GST_DEBUG_OBJECT (aacparse, "setcaps: %s", caps_str);
+ g_free (caps_str);
+
+ /* This is needed at least in case of RTP
+ * Parses the codec_data information to get ObjectType,
+ * number of channels and samplerate */
+ value = gst_structure_get_value (structure, "codec_data");
+ if (value) {
+ GstBuffer *buf = gst_value_get_buffer (value);
+
+ if (buf) {
+ const guint8 *buffer = GST_BUFFER_DATA (buf);
+ guint sr_idx;
+
+ sr_idx = ((buffer[0] & 0x07) << 1) | ((buffer[1] & 0x80) >> 7);
+ aacparse->object_type = (buffer[0] & 0xf8) >> 3;
+ aacparse->sample_rate = gst_aac_parse_get_sample_rate_from_index (sr_idx);
+ aacparse->channels = (buffer[1] & 0x78) >> 3;
+ aacparse->header_type = DSPAAC_HEADER_NONE;
+ aacparse->mpegversion = 4;
+
+ GST_DEBUG ("codec_data: object_type=%d, sample_rate=%d, channels=%d",
+ aacparse->object_type, aacparse->sample_rate, aacparse->channels);
+
+ /* arrange for metadata and get out of the way */
+ gst_aac_parse_set_src_caps (aacparse, caps);
+ gst_base_parse_set_passthrough (parse, TRUE);
+ } else
+ return FALSE;
+
+ /* caps info overrides */
+ gst_structure_get_int (structure, "rate", &aacparse->sample_rate);
+ gst_structure_get_int (structure, "channels", &aacparse->channels);
+ } else {
+ gst_base_parse_set_passthrough (parse, FALSE);
+ }
+
+ return TRUE;
+}
+
+
+/**
+ * gst_aac_parse_adts_get_frame_len:
+ * @data: block of data containing an ADTS header.
+ *
+ * This function calculates ADTS frame length from the given header.
+ *
+ * Returns: size of the ADTS frame.
+ */
+static inline guint
+gst_aac_parse_adts_get_frame_len (const guint8 * data)
+{
+ return ((data[3] & 0x03) << 11) | (data[4] << 3) | ((data[5] & 0xe0) >> 5);
+}
+
+
+/**
+ * gst_aac_parse_check_adts_frame:
+ * @aacparse: #GstAacParse.
+ * @data: Data to be checked.
+ * @avail: Amount of data passed.
+ * @framesize: If valid ADTS frame was found, this will be set to tell the
+ * found frame size in bytes.
+ * @needed_data: If frame was not found, this may be set to tell how much
+ * more data is needed in the next round to detect the frame
+ * reliably. This may happen when a frame header candidate
+ * is found but it cannot be guaranteed to be the header without
+ * peeking the following data.
+ *
+ * Check if the given data contains contains ADTS frame. The algorithm
+ * will examine ADTS frame header and calculate the frame size. Also, another
+ * consecutive ADTS frame header need to be present after the found frame.
+ * Otherwise the data is not considered as a valid ADTS frame. However, this
+ * "extra check" is omitted when EOS has been received. In this case it is
+ * enough when data[0] contains a valid ADTS header.
+ *
+ * This function may set the #needed_data to indicate that a possible frame
+ * candidate has been found, but more data (#needed_data bytes) is needed to
+ * be absolutely sure. When this situation occurs, FALSE will be returned.
+ *
+ * When a valid frame is detected, this function will use
+ * gst_base_parse_set_min_frame_size() function from #GstBaseParse class
+ * to set the needed bytes for next frame.This way next data chunk is already
+ * of correct size.
+ *
+ * Returns: TRUE if the given data contains a valid ADTS header.
+ */
+static gboolean
+gst_aac_parse_check_adts_frame (GstAacParse * aacparse,
+ const guint8 * data, const guint avail, gboolean drain,
+ guint * framesize, guint * needed_data)
+{
+ if (G_UNLIKELY (avail < 2))
+ return FALSE;
+
+ if ((data[0] == 0xff) && ((data[1] & 0xf6) == 0xf0)) {
+ *framesize = gst_aac_parse_adts_get_frame_len (data);
+
+ /* In EOS mode this is enough. No need to examine the data further */
+ if (drain) {
+ return TRUE;
+ }
+
+ if (*framesize + ADTS_MAX_SIZE > avail) {
+ /* We have found a possible frame header candidate, but can't be
+ sure since we don't have enough data to check the next frame */
+ GST_DEBUG ("NEED MORE DATA: we need %d, available %d",
+ *framesize + ADTS_MAX_SIZE, avail);
+ *needed_data = *framesize + ADTS_MAX_SIZE;
+ gst_base_parse_set_min_frame_size (GST_BASE_PARSE (aacparse),
+ *framesize + ADTS_MAX_SIZE);
+ return FALSE;
+ }
+
+ if ((data[*framesize] == 0xff) && ((data[*framesize + 1] & 0xf6) == 0xf0)) {
+ guint nextlen = gst_aac_parse_adts_get_frame_len (data + (*framesize));
+
+ GST_LOG ("ADTS frame found, len: %d bytes", *framesize);
+ gst_base_parse_set_min_frame_size (GST_BASE_PARSE (aacparse),
+ nextlen + ADTS_MAX_SIZE);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/* caller ensure sufficient data */
+static inline void
+gst_aac_parse_parse_adts_header (GstAacParse * aacparse, const guint8 * data,
+ gint * rate, gint * channels, gint * object, gint * version)
+{
+
+ if (rate) {
+ gint sr_idx = (data[2] & 0x3c) >> 2;
+
+ *rate = gst_aac_parse_get_sample_rate_from_index (sr_idx);
+ }
+ if (channels)
+ *channels = ((data[2] & 0x01) << 2) | ((data[3] & 0xc0) >> 6);
+
+ if (version)
+ *version = (data[1] & 0x08) ? 2 : 4;
+ if (object)
+ *object = (data[2] & 0xc0) >> 6;
+}
+
+/**
+ * gst_aac_parse_detect_stream:
+ * @aacparse: #GstAacParse.
+ * @data: A block of data that needs to be examined for stream characteristics.
+ * @avail: Size of the given datablock.
+ * @framesize: If valid stream was found, this will be set to tell the
+ * first frame size in bytes.
+ * @skipsize: If valid stream was found, this will be set to tell the first
+ * audio frame position within the given data.
+ *
+ * Examines the given piece of data and try to detect the format of it. It
+ * checks for "ADIF" header (in the beginning of the clip) and ADTS frame
+ * header. If the stream is detected, TRUE will be returned and #framesize
+ * is set to indicate the found frame size. Additionally, #skipsize might
+ * be set to indicate the number of bytes that need to be skipped, a.k.a. the
+ * position of the frame inside given data chunk.
+ *
+ * Returns: TRUE on success.
+ */
+static gboolean
+gst_aac_parse_detect_stream (GstAacParse * aacparse,
+ const guint8 * data, const guint avail, gboolean drain,
+ guint * framesize, gint * skipsize)
+{
+ gboolean found = FALSE;
+ guint need_data = 0;
+ guint i = 0;
+
+ GST_DEBUG_OBJECT (aacparse, "Parsing header data");
+
+ /* FIXME: No need to check for ADIF if we are not in the beginning of the
+ stream */
+
+ /* Can we even parse the header? */
+ if (avail < ADTS_MAX_SIZE)
+ return FALSE;
+
+ for (i = 0; i < avail - 4; i++) {
+ if (((data[i] == 0xff) && ((data[i + 1] & 0xf6) == 0xf0)) ||
+ strncmp ((char *) data + i, "ADIF", 4) == 0) {
+ found = TRUE;
+
+ if (i) {
+ /* Trick: tell the parent class that we didn't find the frame yet,
+ but make it skip 'i' amount of bytes. Next time we arrive
+ here we have full frame in the beginning of the data. */
+ *skipsize = i;
+ return FALSE;
+ }
+ break;
+ }
+ }
+ if (!found) {
+ if (i)
+ *skipsize = i;
+ return FALSE;
+ }
+
+ if (gst_aac_parse_check_adts_frame (aacparse, data, avail, drain,
+ framesize, &need_data)) {
+ gint rate, channels;
+
+ GST_INFO ("ADTS ID: %d, framesize: %d", (data[1] & 0x08) >> 3, *framesize);
+
+ aacparse->header_type = DSPAAC_HEADER_ADTS;
+ gst_aac_parse_parse_adts_header (aacparse, data, &rate, &channels,
+ &aacparse->object_type, &aacparse->mpegversion);
+
+ gst_base_parse_set_frame_rate (GST_BASE_PARSE (aacparse), rate, 1024, 2, 2);
+
+ GST_DEBUG ("ADTS: samplerate %d, channels %d, objtype %d, version %d",
+ rate, channels, aacparse->object_type, aacparse->mpegversion);
+
+ gst_base_parse_set_syncable (GST_BASE_PARSE (aacparse), TRUE);
+
+ return TRUE;
+ } else if (need_data) {
+ /* This tells the parent class not to skip any data */
+ *skipsize = 0;
+ return FALSE;
+ }
+
+ if (avail < ADIF_MAX_SIZE)
+ return FALSE;
+
+ if (memcmp (data + i, "ADIF", 4) == 0) {
+ const guint8 *adif;
+ int skip_size = 0;
+ int bitstream_type;
+ int sr_idx;
+
+ aacparse->header_type = DSPAAC_HEADER_ADIF;
+ aacparse->mpegversion = 4;
+
+ /* Skip the "ADIF" bytes */
+ adif = data + i + 4;
+
+ /* copyright string */
+ if (adif[0] & 0x80)
+ skip_size += 9; /* skip 9 bytes */
+
+ bitstream_type = adif[0 + skip_size] & 0x10;
+ aacparse->bitrate =
+ ((unsigned int) (adif[0 + skip_size] & 0x0f) << 19) |
+ ((unsigned int) adif[1 + skip_size] << 11) |
+ ((unsigned int) adif[2 + skip_size] << 3) |
+ ((unsigned int) adif[3 + skip_size] & 0xe0);
+
+ /* CBR */
+ if (bitstream_type == 0) {
+#if 0
+ /* Buffer fullness parsing. Currently not needed... */
+ guint num_elems = 0;
+ guint fullness = 0;
+
+ num_elems = (adif[3 + skip_size] & 0x1e);
+ GST_INFO ("ADIF num_config_elems: %d", num_elems);
+
+ fullness = ((unsigned int) (adif[3 + skip_size] & 0x01) << 19) |
+ ((unsigned int) adif[4 + skip_size] << 11) |
+ ((unsigned int) adif[5 + skip_size] << 3) |
+ ((unsigned int) (adif[6 + skip_size] & 0xe0) >> 5);
+
+ GST_INFO ("ADIF buffer fullness: %d", fullness);
+#endif
+ aacparse->object_type = ((adif[6 + skip_size] & 0x01) << 1) |
+ ((adif[7 + skip_size] & 0x80) >> 7);
+ sr_idx = (adif[7 + skip_size] & 0x78) >> 3;
+ }
+ /* VBR */
+ else {
+ aacparse->object_type = (adif[4 + skip_size] & 0x18) >> 3;
+ sr_idx = ((adif[4 + skip_size] & 0x07) << 1) |
+ ((adif[5 + skip_size] & 0x80) >> 7);
+ }
+
+ /* FIXME: This gives totally wrong results. Duration calculation cannot
+ be based on this */
+ aacparse->sample_rate = gst_aac_parse_get_sample_rate_from_index (sr_idx);
+
+ /* baseparse is not given any fps,
+ * so it will give up on timestamps, seeking, etc */
+
+ /* FIXME: Can we assume this? */
+ aacparse->channels = 2;
+
+ GST_INFO ("ADIF: br=%d, samplerate=%d, objtype=%d",
+ aacparse->bitrate, aacparse->sample_rate, aacparse->object_type);
+
+ gst_base_parse_set_min_frame_size (GST_BASE_PARSE (aacparse), 512);
+
+ /* arrange for metadata and get out of the way */
+ gst_aac_parse_set_src_caps (aacparse,
+ GST_PAD_CAPS (GST_BASE_PARSE_SINK_PAD (aacparse)));
+
+ /* not syncable, not easily seekable (unless we push data from start */
+ gst_base_parse_set_syncable (GST_BASE_PARSE_CAST (aacparse), FALSE);
+ gst_base_parse_set_passthrough (GST_BASE_PARSE_CAST (aacparse), TRUE);
+ gst_base_parse_set_average_bitrate (GST_BASE_PARSE_CAST (aacparse), 0);
+
+ *framesize = avail;
+ return TRUE;
+ }
+
+ /* This should never happen */
+ return FALSE;
+}
+
+
+/**
+ * gst_aac_parse_check_valid_frame:
+ * @parse: #GstBaseParse.
+ * @buffer: #GstBuffer.
+ * @framesize: If the buffer contains a valid frame, its size will be put here
+ * @skipsize: How much data parent class should skip in order to find the
+ * frame header.
+ *
+ * Implementation of "check_valid_frame" vmethod in #GstBaseParse class.
+ *
+ * Returns: TRUE if buffer contains a valid frame.
+ */
+gboolean
+gst_aac_parse_check_valid_frame (GstBaseParse * parse,
+ GstBaseParseFrame * frame, guint * framesize, gint * skipsize)
+{
+ const guint8 *data;
+ GstAacParse *aacparse;
+ gboolean ret = FALSE;
+ gboolean lost_sync;
+ GstBuffer *buffer;
+
+ aacparse = GST_AAC_PARSE (parse);
+ buffer = frame->buffer;
+ data = GST_BUFFER_DATA (buffer);
+
+ lost_sync = GST_BASE_PARSE_LOST_SYNC (parse);
+
+ if (aacparse->header_type == DSPAAC_HEADER_ADIF ||
+ aacparse->header_type == DSPAAC_HEADER_NONE) {
+ /* There is nothing to parse */
+ *framesize = GST_BUFFER_SIZE (buffer);
+ ret = TRUE;
+
+ } else if (aacparse->header_type == DSPAAC_HEADER_NOT_PARSED || lost_sync) {
+
+ ret = gst_aac_parse_detect_stream (aacparse, data, GST_BUFFER_SIZE (buffer),
+ GST_BASE_PARSE_DRAINING (parse), framesize, skipsize);
+
+ } else if (aacparse->header_type == DSPAAC_HEADER_ADTS) {
+ guint needed_data = 1024;
+
+ ret = gst_aac_parse_check_adts_frame (aacparse, data,
+ GST_BUFFER_SIZE (buffer), GST_BASE_PARSE_DRAINING (parse),
+ framesize, &needed_data);
+
+ if (!ret) {
+ GST_DEBUG ("buffer didn't contain valid frame");
+ gst_base_parse_set_min_frame_size (GST_BASE_PARSE (aacparse),
+ needed_data);
+ }
+
+ } else {
+ GST_DEBUG ("buffer didn't contain valid frame");
+ gst_base_parse_set_min_frame_size (GST_BASE_PARSE (aacparse), 1024);
+ }
+
+ return ret;
+}
+
+
+/**
+ * gst_aac_parse_parse_frame:
+ * @parse: #GstBaseParse.
+ * @buffer: #GstBuffer.
+ *
+ * Implementation of "parse_frame" vmethod in #GstBaseParse class.
+ *
+ * Also determines frame overhead.
+ * ADTS streams have a 7 byte header in each frame. MP4 and ADIF streams don't have
+ * a per-frame header.
+ *
+ * We're making a couple of simplifying assumptions:
+ *
+ * 1. We count Program Configuration Elements rather than searching for them
+ * in the streams to discount them - the overhead is negligible.
+ *
+ * 2. We ignore CRC. This has a worst-case impact of (num_raw_blocks + 1)*16
+ * bits, which should still not be significant enough to warrant the
+ * additional parsing through the headers
+ *
+ * Returns: GST_FLOW_OK if frame was successfully parsed and can be pushed
+ * forward. Otherwise appropriate error is returned.
+ */
+GstFlowReturn
+gst_aac_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
+{
+ GstAacParse *aacparse;
+ GstBuffer *buffer;
+ GstFlowReturn ret = GST_FLOW_OK;
+ gint rate, channels;
+
+ aacparse = GST_AAC_PARSE (parse);
+ buffer = frame->buffer;
+
+ if (G_UNLIKELY (aacparse->header_type != DSPAAC_HEADER_ADTS))
+ return ret;
+
+ /* see above */
+ frame->overhead = 7;
+
+ gst_aac_parse_parse_adts_header (aacparse, GST_BUFFER_DATA (buffer),
+ &rate, &channels, NULL, NULL);
+ GST_LOG_OBJECT (aacparse, "rate: %d, chans: %d", rate, channels);
+
+ if (G_UNLIKELY (rate != aacparse->sample_rate
+ || channels != aacparse->channels)) {
+ aacparse->sample_rate = rate;
+ aacparse->channels = channels;
+
+ if (!gst_aac_parse_set_src_caps (aacparse,
+ GST_PAD_CAPS (GST_BASE_PARSE (aacparse)->sinkpad))) {
+ /* If linking fails, we need to return appropriate error */
+ ret = GST_FLOW_NOT_LINKED;
+ }
+
+ gst_base_parse_set_frame_rate (GST_BASE_PARSE (aacparse),
+ aacparse->sample_rate, 1024, 2, 2);
+ }
+
+ return ret;
+}
+
+
+/**
+ * gst_aac_parse_start:
+ * @parse: #GstBaseParse.
+ *
+ * Implementation of "start" vmethod in #GstBaseParse class.
+ *
+ * Returns: TRUE if startup succeeded.
+ */
+gboolean
+gst_aac_parse_start (GstBaseParse * parse)
+{
+ GstAacParse *aacparse;
+
+ aacparse = GST_AAC_PARSE (parse);
+ GST_DEBUG ("start");
+ gst_base_parse_set_min_frame_size (GST_BASE_PARSE (aacparse), 1024);
+ return TRUE;
+}
+
+
+/**
+ * gst_aac_parse_stop:
+ * @parse: #GstBaseParse.
+ *
+ * Implementation of "stop" vmethod in #GstBaseParse class.
+ *
+ * Returns: TRUE is stopping succeeded.
+ */
+gboolean
+gst_aac_parse_stop (GstBaseParse * parse)
+{
+ GST_DEBUG ("stop");
+ return TRUE;
+}
diff --git a/gst/audioparsers/gstaacparse.h b/gst/audioparsers/gstaacparse.h
new file mode 100644
index 000000000..4020d8fc7
--- /dev/null
+++ b/gst/audioparsers/gstaacparse.h
@@ -0,0 +1,109 @@
+/* GStreamer AAC parser
+ * Copyright (C) 2008 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Stefan Kost <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_AAC_PARSE_H__
+#define __GST_AAC_PARSE_H__
+
+#include <gst/gst.h>
+#include <gst/base/gstbaseparse.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_AAC_PARSE \
+ (gst_aac_parse_get_type())
+#define GST_AAC_PARSE(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_AAC_PARSE, GstAacParse))
+#define GST_AAC_PARSE_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_AAC_PARSE, GstAacParseClass))
+#define GST_IS_AAC_PARSE(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_AAC_PARSE))
+#define GST_IS_AAC_PARSE_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_AAC_PARSE))
+
+
+/**
+ * GstAacHeaderType:
+ * @DSPAAC_HEADER_NOT_PARSED: Header not parsed yet.
+ * @DSPAAC_HEADER_UNKNOWN: Unknown (not recognized) header.
+ * @DSPAAC_HEADER_ADIF: ADIF header found.
+ * @DSPAAC_HEADER_ADTS: ADTS header found.
+ * @DSPAAC_HEADER_NONE: Raw stream, no header.
+ *
+ * Type header enumeration set in #header_type.
+ */
+typedef enum {
+ DSPAAC_HEADER_NOT_PARSED,
+ DSPAAC_HEADER_UNKNOWN,
+ DSPAAC_HEADER_ADIF,
+ DSPAAC_HEADER_ADTS,
+ DSPAAC_HEADER_NONE
+} GstAacHeaderType;
+
+
+typedef struct _GstAacParse GstAacParse;
+typedef struct _GstAacParseClass GstAacParseClass;
+
+/**
+ * GstAacParse:
+ * @element: the parent element.
+ * @object_type: AAC object type of the stream.
+ * @bitrate: Current media bitrate.
+ * @sample_rate: Current media samplerate.
+ * @channels: Current media channel count.
+ * @frames_per_sec: FPS value of the current stream.
+ * @header_type: #GstAacHeaderType indicating the current stream type.
+ * @framecount: The amount of frames that has been processed this far.
+ * @bytecount: The amount of bytes that has been processed this far.
+ * @sync: Tells whether the parser is in sync (a.k.a. not searching for header)
+ * @eos: End-of-Stream indicator. Set when EOS event arrives.
+ * @duration: Duration of the current stream.
+ * @ts: Current stream timestamp.
+ *
+ * The opaque GstAacParse data structure.
+ */
+struct _GstAacParse {
+ GstBaseParse element;
+
+ /* Stream type -related info */
+ gint object_type;
+ gint bitrate;
+ gint sample_rate;
+ gint channels;
+ gint mpegversion;
+
+ GstAacHeaderType header_type;
+};
+
+/**
+ * GstAacParseClass:
+ * @parent_class: Element parent class.
+ *
+ * The opaque GstAacParseClass data structure.
+ */
+struct _GstAacParseClass {
+ GstBaseParseClass parent_class;
+};
+
+GType gst_aac_parse_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_AAC_PARSE_H__ */
diff --git a/gst/audioparsers/gstac3parse.c b/gst/audioparsers/gstac3parse.c
new file mode 100644
index 000000000..ee22e3db7
--- /dev/null
+++ b/gst/audioparsers/gstac3parse.c
@@ -0,0 +1,507 @@
+/* GStreamer AC3 parser
+ * Copyright (C) 2009 Tim-Philipp Müller <tim centricular net>
+ * Copyright (C) 2009 Mark Nauwelaerts <mnauw users sf net>
+ * Copyright (C) 2009 Nokia Corporation. All rights reserved.
+ * Contact: Stefan Kost <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-ac3parse
+ * @short_description: AC3 parser
+ * @see_also: #GstAmrParse, #GstAACParse
+ *
+ * This is an AC3 parser.
+ *
+ * <refsect2>
+ * <title>Example launch line</title>
+ * |[
+ * gst-launch filesrc location=abc.ac3 ! ac3parse ! a52dec ! audioresample ! audioconvert ! autoaudiosink
+ * ]|
+ * </refsect2>
+ */
+
+/* TODO:
+ * - add support for audio/x-private1-ac3 as well
+ * - should accept framed and unframed input (needs decodebin fixes first)
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+
+#include "gstac3parse.h"
+#include <gst/base/gstbytereader.h>
+#include <gst/base/gstbitreader.h>
+
+GST_DEBUG_CATEGORY_STATIC (ac3_parse_debug);
+#define GST_CAT_DEFAULT ac3_parse_debug
+
+static const struct
+{
+ const guint bit_rate; /* nominal bit rate */
+ const guint frame_size[3]; /* frame size for 32kHz, 44kHz, and 48kHz */
+} frmsizcod_table[38] = {
+ {
+ 32, {
+ 64, 69, 96}}, {
+ 32, {
+ 64, 70, 96}}, {
+ 40, {
+ 80, 87, 120}}, {
+ 40, {
+ 80, 88, 120}}, {
+ 48, {
+ 96, 104, 144}}, {
+ 48, {
+ 96, 105, 144}}, {
+ 56, {
+ 112, 121, 168}}, {
+ 56, {
+ 112, 122, 168}}, {
+ 64, {
+ 128, 139, 192}}, {
+ 64, {
+ 128, 140, 192}}, {
+ 80, {
+ 160, 174, 240}}, {
+ 80, {
+ 160, 175, 240}}, {
+ 96, {
+ 192, 208, 288}}, {
+ 96, {
+ 192, 209, 288}}, {
+ 112, {
+ 224, 243, 336}}, {
+ 112, {
+ 224, 244, 336}}, {
+ 128, {
+ 256, 278, 384}}, {
+ 128, {
+ 256, 279, 384}}, {
+ 160, {
+ 320, 348, 480}}, {
+ 160, {
+ 320, 349, 480}}, {
+ 192, {
+ 384, 417, 576}}, {
+ 192, {
+ 384, 418, 576}}, {
+ 224, {
+ 448, 487, 672}}, {
+ 224, {
+ 448, 488, 672}}, {
+ 256, {
+ 512, 557, 768}}, {
+ 256, {
+ 512, 558, 768}}, {
+ 320, {
+ 640, 696, 960}}, {
+ 320, {
+ 640, 697, 960}}, {
+ 384, {
+ 768, 835, 1152}}, {
+ 384, {
+ 768, 836, 1152}}, {
+ 448, {
+ 896, 975, 1344}}, {
+ 448, {
+ 896, 976, 1344}}, {
+ 512, {
+ 1024, 1114, 1536}}, {
+ 512, {
+ 1024, 1115, 1536}}, {
+ 576, {
+ 1152, 1253, 1728}}, {
+ 576, {
+ 1152, 1254, 1728}}, {
+ 640, {
+ 1280, 1393, 1920}}, {
+ 640, {
+ 1280, 1394, 1920}}
+};
+
+static const guint fscod_rates[4] = { 48000, 44100, 32000, 0 };
+static const guint acmod_chans[8] = { 2, 1, 2, 3, 3, 4, 4, 5 };
+static const guint numblks[4] = { 1, 2, 3, 6 };
+
+static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS ("audio/x-ac3, framed = (boolean) true, "
+ " channels = (int) [ 1, 6 ], rate = (int) [ 32000, 48000 ]; "
+ "audio/x-eac3, framed = (boolean) true, "
+ " channels = (int) [ 1, 6 ], rate = (int) [ 32000, 48000 ] "));
+
+static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS ("audio/x-ac3, framed = (boolean) false; "
+ "audio/x-eac3, framed = (boolean) false; "
+ "audio/ac3, framed = (boolean) false "));
+
+static void gst_ac3_parse_finalize (GObject * object);
+
+static gboolean gst_ac3_parse_start (GstBaseParse * parse);
+static gboolean gst_ac3_parse_stop (GstBaseParse * parse);
+static gboolean gst_ac3_parse_check_valid_frame (GstBaseParse * parse,
+ GstBaseParseFrame * frame, guint * size, gint * skipsize);
+static GstFlowReturn gst_ac3_parse_parse_frame (GstBaseParse * parse,
+ GstBaseParseFrame * frame);
+
+GST_BOILERPLATE (GstAc3Parse, gst_ac3_parse, GstBaseParse, GST_TYPE_BASE_PARSE);
+
+static void
+gst_ac3_parse_base_init (gpointer klass)
+{
+ GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+
+ 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,
+ "AC3 audio stream parser", "Codec/Parser/Audio",
+ "AC3 parser", "Tim-Philipp Müller <tim centricular net>");
+}
+
+static void
+gst_ac3_parse_class_init (GstAc3ParseClass * klass)
+{
+ GstBaseParseClass *parse_class = GST_BASE_PARSE_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ GST_DEBUG_CATEGORY_INIT (ac3_parse_debug, "ac3parse", 0,
+ "AC3 audio stream parser");
+
+ object_class->finalize = gst_ac3_parse_finalize;
+
+ parse_class->start = GST_DEBUG_FUNCPTR (gst_ac3_parse_start);
+ parse_class->stop = GST_DEBUG_FUNCPTR (gst_ac3_parse_stop);
+ parse_class->check_valid_frame =
+ GST_DEBUG_FUNCPTR (gst_ac3_parse_check_valid_frame);
+ parse_class->parse_frame = GST_DEBUG_FUNCPTR (gst_ac3_parse_parse_frame);
+}
+
+static void
+gst_ac3_parse_reset (GstAc3Parse * ac3parse)
+{
+ ac3parse->channels = -1;
+ ac3parse->sample_rate = -1;
+ ac3parse->eac = FALSE;
+}
+
+static void
+gst_ac3_parse_init (GstAc3Parse * ac3parse, GstAc3ParseClass * klass)
+{
+ gst_base_parse_set_min_frame_size (GST_BASE_PARSE (ac3parse), 64 * 2);
+ gst_ac3_parse_reset (ac3parse);
+}
+
+static void
+gst_ac3_parse_finalize (GObject * object)
+{
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static gboolean
+gst_ac3_parse_start (GstBaseParse * parse)
+{
+ GstAc3Parse *ac3parse = GST_AC3_PARSE (parse);
+
+ GST_DEBUG_OBJECT (parse, "starting");
+
+ gst_ac3_parse_reset (ac3parse);
+
+ return TRUE;
+}
+
+static gboolean
+gst_ac3_parse_stop (GstBaseParse * parse)
+{
+ GST_DEBUG_OBJECT (parse, "stopping");
+
+ return TRUE;
+}
+
+static gboolean
+gst_ac3_parse_frame_header_ac3 (GstAc3Parse * ac3parse, GstBuffer * buf,
+ guint * frame_size, guint * rate, guint * chans, guint * blks, guint * sid)
+{
+ GstBitReader bits = GST_BIT_READER_INIT_FROM_BUFFER (buf);
+ guint8 fscod, frmsizcod, bsid, acmod, lfe_on;
+
+ GST_LOG_OBJECT (ac3parse, "parsing ac3");
+
+ gst_bit_reader_skip_unchecked (&bits, 16 + 16);
+ fscod = gst_bit_reader_get_bits_uint8_unchecked (&bits, 2);
+ frmsizcod = gst_bit_reader_get_bits_uint8_unchecked (&bits, 6);
+
+ if (G_UNLIKELY (fscod == 3 || frmsizcod >= G_N_ELEMENTS (frmsizcod_table))) {
+ GST_DEBUG_OBJECT (ac3parse, "bad fscod=%d frmsizcod=%d", fscod, frmsizcod);
+ return FALSE;
+ }
+
+ bsid = gst_bit_reader_get_bits_uint8_unchecked (&bits, 5);
+ gst_bit_reader_skip_unchecked (&bits, 3); /* bsmod */
+ acmod = gst_bit_reader_get_bits_uint8_unchecked (&bits, 3);
+
+ /* spec not quite clear here: decoder should decode if less than 8,
+ * but seemingly only defines 6 and 8 cases */
+ if (bsid > 8) {
+ GST_DEBUG_OBJECT (ac3parse, "unexpected bsid=%d", bsid);
+ return FALSE;
+ } else if (bsid != 8 && bsid != 6) {
+ GST_DEBUG_OBJECT (ac3parse, "undefined bsid=%d", bsid);
+ }
+
+ if ((acmod & 0x1) && (acmod != 0x1)) /* 3 front channels */
+ gst_bit_reader_skip_unchecked (&bits, 2);
+ if ((acmod & 0x4)) /* if a surround channel exists */
+ gst_bit_reader_skip_unchecked (&bits, 2);
+ if (acmod == 0x2) /* if in 2/0 mode */
+ gst_bit_reader_skip_unchecked (&bits, 2);
+
+ lfe_on = gst_bit_reader_get_bits_uint8_unchecked (&bits, 1);
+
+ if (frame_size)
+ *frame_size = frmsizcod_table[frmsizcod].frame_size[fscod] * 2;
+ if (rate)
+ *rate = fscod_rates[fscod];
+ if (chans)
+ *chans = acmod_chans[acmod] + lfe_on;
+ if (blks)
+ *blks = 6;
+ if (sid)
+ *sid = 0;
+
+ return TRUE;
+}
+
+static gboolean
+gst_ac3_parse_frame_header_eac3 (GstAc3Parse * ac3parse, GstBuffer * buf,
+ guint * frame_size, guint * rate, guint * chans, guint * blks, guint * sid)
+{
+ GstBitReader bits = GST_BIT_READER_INIT_FROM_BUFFER (buf);
+ guint16 frmsiz, sample_rate, blocks;
+ guint8 strmtyp, fscod, fscod2, acmod, lfe_on, strmid, numblkscod;
+
+ GST_LOG_OBJECT (ac3parse, "parsing e-ac3");
+
+ gst_bit_reader_skip_unchecked (&bits, 16);
+ strmtyp = gst_bit_reader_get_bits_uint8_unchecked (&bits, 2); /* strmtyp */
+ if (G_UNLIKELY (strmtyp == 3)) {
+ GST_DEBUG_OBJECT (ac3parse, "bad strmtyp %d", strmtyp);
+ return FALSE;
+ }
+
+ strmid = gst_bit_reader_get_bits_uint8_unchecked (&bits, 3); /* substreamid */
+ frmsiz = gst_bit_reader_get_bits_uint16_unchecked (&bits, 11); /* frmsiz */
+ fscod = gst_bit_reader_get_bits_uint8_unchecked (&bits, 2); /* fscod */
+ if (fscod == 3) {
+ fscod2 = gst_bit_reader_get_bits_uint8_unchecked (&bits, 2); /* fscod2 */
+ if (G_UNLIKELY (fscod2 == 3)) {
+ GST_DEBUG_OBJECT (ac3parse, "invalid fscod2");
+ return FALSE;
+ }
+ sample_rate = fscod_rates[fscod2] / 2;
+ blocks = 6;
+ } else {
+ numblkscod = gst_bit_reader_get_bits_uint8_unchecked (&bits, 2); /* numblkscod */
+ sample_rate = fscod_rates[fscod];
+ blocks = numblks[numblkscod];
+ }
+
+ acmod = gst_bit_reader_get_bits_uint8_unchecked (&bits, 3); /* acmod */
+ lfe_on = gst_bit_reader_get_bits_uint8_unchecked (&bits, 1); /* lfeon */
+
+ gst_bit_reader_skip_unchecked (&bits, 5); /* bsid */
+
+ if (frame_size)
+ *frame_size = (frmsiz + 1) * 2;
+ if (rate)
+ *rate = sample_rate;
+ if (chans)
+ *chans = acmod_chans[acmod] + lfe_on;
+ if (blks)
+ *blks = blocks;
+ if (sid)
+ *sid = (strmtyp & 0x1) << 3 | strmid;
+
+ return TRUE;
+}
+
+static gboolean
+gst_ac3_parse_frame_header (GstAc3Parse * parse, GstBuffer * buf,
+ guint * framesize, guint * rate, guint * chans, guint * blocks,
+ guint * sid, gboolean * eac)
+{
+ GstBitReader bits = GST_BIT_READER_INIT_FROM_BUFFER (buf);
+ guint16 sync;
+ guint8 bsid;
+
+ GST_MEMDUMP_OBJECT (parse, "AC3 frame sync", GST_BUFFER_DATA (buf), 16);
+
+ sync = gst_bit_reader_get_bits_uint16_unchecked (&bits, 16);
+ gst_bit_reader_skip_unchecked (&bits, 16 + 8);
+ bsid = gst_bit_reader_peek_bits_uint8_unchecked (&bits, 5);
+
+ if (G_UNLIKELY (sync != 0x0b77))
+ return FALSE;
+
+ GST_LOG_OBJECT (parse, "bsid = %d", bsid);
+
+ if (bsid <= 10) {
+ if (eac)
+ *eac = FALSE;
+ return gst_ac3_parse_frame_header_ac3 (parse, buf, framesize, rate, chans,
+ blocks, sid);
+ } else if (bsid <= 16) {
+ if (eac)
+ *eac = TRUE;
+ return gst_ac3_parse_frame_header_eac3 (parse, buf, framesize, rate, chans,
+ blocks, sid);
+ } else {
+ GST_DEBUG_OBJECT (parse, "unexpected bsid %d", bsid);
+ return FALSE;
+ }
+}
+
+static gboolean
+gst_ac3_parse_check_valid_frame (GstBaseParse * parse,
+ GstBaseParseFrame * frame, guint * framesize, gint * skipsize)
+{
+ GstAc3Parse *ac3parse = GST_AC3_PARSE (parse);
+ GstBuffer *buf = frame->buffer;
+ GstByteReader reader = GST_BYTE_READER_INIT_FROM_BUFFER (buf);
+ gint off;
+ gboolean lost_sync, draining;
+
+ if (G_UNLIKELY (GST_BUFFER_SIZE (buf) < 6))
+ return FALSE;
+
+ off = gst_byte_reader_masked_scan_uint32 (&reader, 0xffff0000, 0x0b770000,
+ 0, GST_BUFFER_SIZE (buf));
+
+ GST_LOG_OBJECT (parse, "possible sync at buffer offset %d", off);
+
+ /* didn't find anything that looks like a sync word, skip */
+ if (off < 0) {
+ *skipsize = GST_BUFFER_SIZE (buf) - 3;
+ return FALSE;
+ }
+
+ /* possible frame header, but not at offset 0? skip bytes before sync */
+ if (off > 0) {
+ *skipsize = off;
+ return FALSE;
+ }
+
+ /* make sure the values in the frame header look sane */
+ if (!gst_ac3_parse_frame_header (ac3parse, buf, framesize, NULL, NULL,
+ NULL, NULL, NULL)) {
+ *skipsize = off + 2;
+ return FALSE;
+ }
+
+ GST_LOG_OBJECT (parse, "got frame");
+
+ lost_sync = GST_BASE_PARSE_LOST_SYNC (parse);
+ draining = GST_BASE_PARSE_DRAINING (parse);
+
+ if (lost_sync && !draining) {
+ guint16 word = 0;
+
+ GST_DEBUG_OBJECT (ac3parse, "resyncing; checking next frame syncword");
+
+ if (!gst_byte_reader_skip (&reader, *framesize) ||
+ !gst_byte_reader_get_uint16_be (&reader, &word)) {
+ GST_DEBUG_OBJECT (ac3parse, "... but not sufficient data");
+ gst_base_parse_set_min_frame_size (parse, *framesize + 6);
+ *skipsize = 0;
+ return FALSE;
+ } else {
+ if (word != 0x0b77) {
+ GST_DEBUG_OBJECT (ac3parse, "0x%x not OK", word);
+ *skipsize = off + 2;
+ return FALSE;
+ } else {
+ /* ok, got sync now, let's assume constant frame size */
+ gst_base_parse_set_min_frame_size (parse, *framesize);
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+static GstFlowReturn
+gst_ac3_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
+{
+ GstAc3Parse *ac3parse = GST_AC3_PARSE (parse);
+ GstBuffer *buf = frame->buffer;
+ guint fsize, rate, chans, blocks, sid;
+ gboolean eac;
+
+ if (!gst_ac3_parse_frame_header (ac3parse, buf, &fsize, &rate, &chans,
+ &blocks, &sid, &eac))
+ goto broken_header;
+
+ GST_LOG_OBJECT (parse, "size: %u, rate: %u, chans: %u", fsize, rate, chans);
+
+ if (G_UNLIKELY (sid)) {
+ /* dependent frame, no need to (ac)count for or consider further */
+ GST_LOG_OBJECT (parse, "sid: %d", sid);
+ frame->flags |= GST_BASE_PARSE_FRAME_FLAG_NO_FRAME;
+ /* TODO maybe also mark as DELTA_UNIT,
+ * if that does not surprise baseparse elsewhere */
+ /* occupies same time space as previous base frame */
+ if (G_LIKELY (GST_BUFFER_TIMESTAMP (buf) >= GST_BUFFER_DURATION (buf)))
+ GST_BUFFER_TIMESTAMP (buf) -= GST_BUFFER_DURATION (buf);
+ /* only return if we already arranged for caps */
+ if (G_LIKELY (ac3parse->sample_rate > 0))
+ return GST_FLOW_OK;
+ }
+
+ if (G_UNLIKELY (ac3parse->sample_rate != rate || ac3parse->channels != chans
+ || ac3parse->eac != ac3parse->eac)) {
+ GstCaps *caps = gst_caps_new_simple (eac ? "audio/x-eac3" : "audio/x-ac3",
+ "framed", G_TYPE_BOOLEAN, TRUE, "rate", G_TYPE_INT, rate,
+ "channels", G_TYPE_INT, chans, NULL);
+ gst_buffer_set_caps (buf, caps);
+ gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (parse), caps);
+ gst_caps_unref (caps);
+
+ ac3parse->sample_rate = rate;
+ ac3parse->channels = chans;
+ ac3parse->eac = eac;
+
+ gst_base_parse_set_frame_rate (parse, rate, 256 * blocks, 2, 2);
+ }
+
+ return GST_FLOW_OK;
+
+/* ERRORS */
+broken_header:
+ {
+ /* this really shouldn't ever happen */
+ GST_ELEMENT_ERROR (parse, STREAM, DECODE, (NULL), (NULL));
+ return GST_FLOW_ERROR;
+ }
+}
diff --git a/gst/audioparsers/gstac3parse.h b/gst/audioparsers/gstac3parse.h
new file mode 100644
index 000000000..6ed01ddf5
--- /dev/null
+++ b/gst/audioparsers/gstac3parse.h
@@ -0,0 +1,73 @@
+/* GStreamer AC3 parser
+ * Copyright (C) 2009 Tim-Philipp Müller <tim centricular net>
+ * Copyright (C) 2009 Mark Nauwelaerts <mnauw users sf net>
+ * Copyright (C) 2009 Nokia Corporation. All rights reserved.
+ * Contact: Stefan Kost <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_AC3_PARSE_H__
+#define __GST_AC3_PARSE_H__
+
+#include <gst/gst.h>
+#include <gst/base/gstbaseparse.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_AC3_PARSE \
+ (gst_ac3_parse_get_type())
+#define GST_AC3_PARSE(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_AC3_PARSE, GstAc3Parse))
+#define GST_AC3_PARSE_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_AC3_PARSE, GstAc3ParseClass))
+#define GST_IS_AC3_PARSE(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_AC3_PARSE))
+#define GST_IS_AC3_PARSE_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_AC3_PARSE))
+
+typedef struct _GstAc3Parse GstAc3Parse;
+typedef struct _GstAc3ParseClass GstAc3ParseClass;
+
+/**
+ * GstAc3Parse:
+ *
+ * The opaque GstAc3Parse object
+ */
+struct _GstAc3Parse {
+ GstBaseParse baseparse;
+
+ /*< private >*/
+ gint sample_rate;
+ gint channels;
+ gboolean eac;
+};
+
+/**
+ * GstAc3ParseClass:
+ * @parent_class: Element parent class.
+ *
+ * The opaque GstAc3ParseClass data structure.
+ */
+struct _GstAc3ParseClass {
+ GstBaseParseClass baseparse_class;
+};
+
+GType gst_ac3_parse_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_AC3_PARSE_H__ */
diff --git a/gst/audioparsers/gstamrparse.c b/gst/audioparsers/gstamrparse.c
new file mode 100644
index 000000000..99d31b9ef
--- /dev/null
+++ b/gst/audioparsers/gstamrparse.c
@@ -0,0 +1,378 @@
+/* GStreamer Adaptive Multi-Rate parser plugin
+ * Copyright (C) 2006 Edgard Lima <edgard.lima@indt.org.br>
+ * Copyright (C) 2008 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Stefan Kost <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-amrparse
+ * @short_description: AMR parser
+ * @see_also: #GstAmrnbDec, #GstAmrnbEnc
+ *
+ * This is an AMR parser capable of handling both narrow-band and wideband
+ * formats.
+ *
+ * <refsect2>
+ * <title>Example launch line</title>
+ * |[
+ * gst-launch filesrc location=abc.amr ! amrparse ! amrdec ! audioresample ! audioconvert ! alsasink
+ * ]|
+ * </refsect2>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+
+#include "gstamrparse.h"
+
+
+static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS ("audio/AMR, " "rate = (int) 8000, " "channels = (int) 1;"
+ "audio/AMR-WB, " "rate = (int) 16000, " "channels = (int) 1;")
+ );
+
+static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS ("audio/x-amr-nb-sh; audio/x-amr-wb-sh"));
+
+GST_DEBUG_CATEGORY_STATIC (amrparse_debug);
+#define GST_CAT_DEFAULT amrparse_debug
+
+static const gint block_size_nb[16] =
+ { 12, 13, 15, 17, 19, 20, 26, 31, 5, 0, 0, 0, 0, 0, 0, 0 };
+
+static const gint block_size_wb[16] =
+ { 17, 23, 32, 36, 40, 46, 50, 58, 60, 5, -1, -1, -1, -1, 0, 0 };
+
+/* AMR has a "hardcoded" framerate of 50fps */
+#define AMR_FRAMES_PER_SECOND 50
+#define AMR_FRAME_DURATION (GST_SECOND/AMR_FRAMES_PER_SECOND)
+#define AMR_MIME_HEADER_SIZE 9
+
+gboolean gst_amr_parse_start (GstBaseParse * parse);
+gboolean gst_amr_parse_stop (GstBaseParse * parse);
+
+static gboolean gst_amr_parse_sink_setcaps (GstBaseParse * parse,
+ GstCaps * caps);
+
+gboolean gst_amr_parse_check_valid_frame (GstBaseParse * parse,
+ GstBaseParseFrame * frame, guint * framesize, gint * skipsize);
+
+GstFlowReturn gst_amr_parse_parse_frame (GstBaseParse * parse,
+ GstBaseParseFrame * frame);
+
+#define _do_init(bla) \
+ GST_DEBUG_CATEGORY_INIT (amrparse_debug, "amrparse", 0, \
+ "AMR-NB audio stream parser");
+
+GST_BOILERPLATE_FULL (GstAmrParse, gst_amr_parse, GstBaseParse,
+ GST_TYPE_BASE_PARSE, _do_init);
+
+
+/**
+ * gst_amr_parse_base_init:
+ * @klass: #GstElementClass.
+ *
+ */
+static void
+gst_amr_parse_base_init (gpointer klass)
+{
+ GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+
+ 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,
+ "AMR audio stream parser", "Codec/Parser/Audio",
+ "Adaptive Multi-Rate audio parser",
+ "Ronald Bultje <rbultje@ronald.bitfreak.net>");
+}
+
+
+/**
+ * gst_amr_parse_class_init:
+ * @klass: GstAmrParseClass.
+ *
+ */
+static void
+gst_amr_parse_class_init (GstAmrParseClass * klass)
+{
+ GstBaseParseClass *parse_class = GST_BASE_PARSE_CLASS (klass);
+
+ parse_class->start = GST_DEBUG_FUNCPTR (gst_amr_parse_start);
+ parse_class->stop = GST_DEBUG_FUNCPTR (gst_amr_parse_stop);
+ parse_class->set_sink_caps = GST_DEBUG_FUNCPTR (gst_amr_parse_sink_setcaps);
+ parse_class->parse_frame = GST_DEBUG_FUNCPTR (gst_amr_parse_parse_frame);
+ parse_class->check_valid_frame =
+ GST_DEBUG_FUNCPTR (gst_amr_parse_check_valid_frame);
+}
+
+
+/**
+ * gst_amr_parse_init:
+ * @amrparse: #GstAmrParse
+ * @klass: #GstAmrParseClass.
+ *
+ */
+static void
+gst_amr_parse_init (GstAmrParse * amrparse, GstAmrParseClass * klass)
+{
+ /* init rest */
+ gst_base_parse_set_min_frame_size (GST_BASE_PARSE (amrparse), 62);
+ GST_DEBUG ("initialized");
+
+}
+
+
+/**
+ * gst_amr_parse_set_src_caps:
+ * @amrparse: #GstAmrParse.
+ *
+ * Set source pad caps according to current knowledge about the
+ * audio stream.
+ *
+ * Returns: TRUE if caps were successfully set.
+ */
+static gboolean
+gst_amr_parse_set_src_caps (GstAmrParse * amrparse)
+{
+ GstCaps *src_caps = NULL;
+ gboolean res = FALSE;
+
+ if (amrparse->wide) {
+ GST_DEBUG_OBJECT (amrparse, "setting srcpad caps to AMR-WB");
+ src_caps = gst_caps_new_simple ("audio/AMR-WB",
+ "channels", G_TYPE_INT, 1, "rate", G_TYPE_INT, 16000, NULL);
+ } else {
+ GST_DEBUG_OBJECT (amrparse, "setting srcpad caps to AMR-NB");
+ /* Max. size of NB frame is 31 bytes, so we can set the min. frame
+ size to 32 (+1 for next frame header) */
+ gst_base_parse_set_min_frame_size (GST_BASE_PARSE (amrparse), 32);
+ src_caps = gst_caps_new_simple ("audio/AMR",
+ "channels", G_TYPE_INT, 1, "rate", G_TYPE_INT, 8000, NULL);
+ }
+ gst_pad_use_fixed_caps (GST_BASE_PARSE (amrparse)->srcpad);
+ res = gst_pad_set_caps (GST_BASE_PARSE (amrparse)->srcpad, src_caps);
+ gst_caps_unref (src_caps);
+ return res;
+}
+
+
+/**
+ * gst_amr_parse_sink_setcaps:
+ * @sinkpad: GstPad
+ * @caps: GstCaps
+ *
+ * Returns: TRUE on success.
+ */
+static gboolean
+gst_amr_parse_sink_setcaps (GstBaseParse * parse, GstCaps * caps)
+{
+ GstAmrParse *amrparse;
+ GstStructure *structure;
+ const gchar *name;
+
+ amrparse = GST_AMR_PARSE (parse);
+ structure = gst_caps_get_structure (caps, 0);
+ name = gst_structure_get_name (structure);
+
+ GST_DEBUG_OBJECT (amrparse, "setcaps: %s", name);
+
+ if (!strncmp (name, "audio/x-amr-wb-sh", 17)) {
+ amrparse->block_size = block_size_wb;
+ amrparse->wide = 1;
+ } else if (!strncmp (name, "audio/x-amr-nb-sh", 17)) {
+ amrparse->block_size = block_size_nb;
+ amrparse->wide = 0;
+ } else {
+ GST_WARNING ("Unknown caps");
+ return FALSE;
+ }
+
+ amrparse->need_header = FALSE;
+ gst_base_parse_set_frame_rate (GST_BASE_PARSE (amrparse), 50, 1, 2, 2);
+ gst_amr_parse_set_src_caps (amrparse);
+ return TRUE;
+}
+
+/**
+ * gst_amr_parse_parse_header:
+ * @amrparse: #GstAmrParse
+ * @data: Header data to be parsed.
+ * @skipsize: Output argument where the frame size will be stored.
+ *
+ * Check if the given data contains an AMR mime header.
+ *
+ * Returns: TRUE on success.
+ */
+static gboolean
+gst_amr_parse_parse_header (GstAmrParse * amrparse,
+ const guint8 * data, gint * skipsize)
+{
+ GST_DEBUG_OBJECT (amrparse, "Parsing header data");
+
+ if (!memcmp (data, "#!AMR-WB\n", 9)) {
+ GST_DEBUG_OBJECT (amrparse, "AMR-WB detected");
+ amrparse->block_size = block_size_wb;
+ amrparse->wide = TRUE;
+ *skipsize = amrparse->header = 9;
+ } else if (!memcmp (data, "#!AMR\n", 6)) {
+ GST_DEBUG_OBJECT (amrparse, "AMR-NB detected");
+ amrparse->block_size = block_size_nb;
+ amrparse->wide = FALSE;
+ *skipsize = amrparse->header = 6;
+ } else
+ return FALSE;
+
+ gst_amr_parse_set_src_caps (amrparse);
+ return TRUE;
+}
+
+
+/**
+ * gst_amr_parse_check_valid_frame:
+ * @parse: #GstBaseParse.
+ * @buffer: #GstBuffer.
+ * @framesize: Output variable where the found frame size is put.
+ * @skipsize: Output variable which tells how much data needs to be skipped
+ * until a frame header is found.
+ *
+ * Implementation of "check_valid_frame" vmethod in #GstBaseParse class.
+ *
+ * Returns: TRUE if the given data contains valid frame.
+ */
+gboolean
+gst_amr_parse_check_valid_frame (GstBaseParse * parse,
+ GstBaseParseFrame * frame, guint * framesize, gint * skipsize)
+{
+ GstBuffer *buffer;
+ const guint8 *data;
+ gint fsize, mode, dsize;
+ GstAmrParse *amrparse;
+
+ amrparse = GST_AMR_PARSE (parse);
+ buffer = frame->buffer;
+ data = GST_BUFFER_DATA (buffer);
+ dsize = GST_BUFFER_SIZE (buffer);
+
+ GST_LOG ("buffer: %d bytes", dsize);
+
+ if (amrparse->need_header) {
+ if (dsize >= AMR_MIME_HEADER_SIZE &&
+ gst_amr_parse_parse_header (amrparse, data, skipsize)) {
+ amrparse->need_header = FALSE;
+ gst_base_parse_set_frame_rate (GST_BASE_PARSE (amrparse), 50, 1, 2, 2);
+ } else {
+ GST_WARNING ("media doesn't look like a AMR format");
+ }
+ /* We return FALSE, so this frame won't get pushed forward. Instead,
+ the "skip" value is set, so next time we will receive a valid frame. */
+ return FALSE;
+ }
+
+ /* Does this look like a possible frame header candidate? */
+ if ((data[0] & 0x83) == 0) {
+ /* Yep. Retrieve the frame size */
+ mode = (data[0] >> 3) & 0x0F;
+ fsize = amrparse->block_size[mode] + 1; /* +1 for the header byte */
+
+ /* We recognize this data as a valid frame when:
+ * - We are in sync. There is no need for extra checks then
+ * - We are in EOS. There might not be enough data to check next frame
+ * - Sync is lost, but the following data after this frame seem
+ * to contain a valid header as well (and there is enough data to
+ * perform this check)
+ */
+ if (fsize &&
+ (!GST_BASE_PARSE_LOST_SYNC (parse) || GST_BASE_PARSE_DRAINING (parse)
+ || (dsize > fsize && (data[fsize] & 0x83) == 0))) {
+ *framesize = fsize;
+ return TRUE;
+ }
+ }
+
+ GST_LOG ("sync lost");
+ return FALSE;
+}
+
+
+/**
+ * gst_amr_parse_parse_frame:
+ * @parse: #GstBaseParse.
+ * @buffer: #GstBuffer.
+ *
+ * Implementation of "parse" vmethod in #GstBaseParse class.
+ *
+ * Returns: #GstFlowReturn defining the parsing status.
+ */
+GstFlowReturn
+gst_amr_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
+{
+ return GST_FLOW_OK;
+}
+
+
+/**
+ * gst_amr_parse_start:
+ * @parse: #GstBaseParse.
+ *
+ * Implementation of "start" vmethod in #GstBaseParse class.
+ *
+ * Returns: TRUE on success.
+ */
+gboolean
+gst_amr_parse_start (GstBaseParse * parse)
+{
+ GstAmrParse *amrparse;
+
+ amrparse = GST_AMR_PARSE (parse);
+ GST_DEBUG ("start");
+ amrparse->need_header = TRUE;
+ amrparse->header = 0;
+ return TRUE;
+}
+
+
+/**
+ * gst_amr_parse_stop:
+ * @parse: #GstBaseParse.
+ *
+ * Implementation of "stop" vmethod in #GstBaseParse class.
+ *
+ * Returns: TRUE on success.
+ */
+gboolean
+gst_amr_parse_stop (GstBaseParse * parse)
+{
+ GstAmrParse *amrparse;
+
+ amrparse = GST_AMR_PARSE (parse);
+ GST_DEBUG ("stop");
+ amrparse->need_header = TRUE;
+ amrparse->header = 0;
+ return TRUE;
+}
diff --git a/gst/audioparsers/gstamrparse.h b/gst/audioparsers/gstamrparse.h
new file mode 100644
index 000000000..86a26e026
--- /dev/null
+++ b/gst/audioparsers/gstamrparse.h
@@ -0,0 +1,82 @@
+/* GStreamer Adaptive Multi-Rate parser
+ * Copyright (C) 2004 Ronald Bultje <rbultje@ronald.bitfreak.net>
+ * Copyright (C) 2008 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Stefan Kost <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_AMR_PARSE_H__
+#define __GST_AMR_PARSE_H__
+
+#include <gst/gst.h>
+#include <gst/base/gstbaseparse.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_AMR_PARSE \
+ (gst_amr_parse_get_type())
+#define GST_AMR_PARSE(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_AMR_PARSE, GstAmrParse))
+#define GST_AMR_PARSE_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_AMR_PARSE, GstAmrParseClass))
+#define GST_IS_AMR_PARSE(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_AMR_PARSE))
+#define GST_IS_AMR_PARSE_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_AMR_PARSE))
+
+
+typedef struct _GstAmrParse GstAmrParse;
+typedef struct _GstAmrParseClass GstAmrParseClass;
+
+/**
+ * GstAmrParse:
+ * @element: the parent element.
+ * @block_size: Pointer to frame size lookup table.
+ * @need_header: Tells whether the MIME header should be read in the beginning.
+ * @wide: Wideband mode.
+ * @eos: Indicates the EOS situation. Set when EOS event is received.
+ * @sync: Tells whether the parser is in sync.
+ * @framecount: Total amount of frames handled.
+ * @bytecount: Total amount of bytes handled.
+ * @ts: Timestamp of the current media.
+ *
+ * The opaque GstAacParse data structure.
+ */
+struct _GstAmrParse {
+ GstBaseParse element;
+ const gint *block_size;
+ gboolean need_header;
+ gint header;
+ gboolean wide;
+};
+
+/**
+ * GstAmrParseClass:
+ * @parent_class: Element parent class.
+ *
+ * The opaque GstAmrParseClass data structure.
+ */
+struct _GstAmrParseClass {
+ GstBaseParseClass parent_class;
+};
+
+GType gst_amr_parse_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_AMR_PARSE_H__ */
diff --git a/gst/audioparsers/gstdcaparse.c b/gst/audioparsers/gstdcaparse.c
new file mode 100644
index 000000000..2bf0e3882
--- /dev/null
+++ b/gst/audioparsers/gstdcaparse.c
@@ -0,0 +1,451 @@
+/* GStreamer DCA parser
+ * Copyright (C) 2010 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-dcaparse
+ * @short_description: DCA (DTS Coherent Acoustics) parser
+ * @see_also: #GstAmrParse, #GstAACParse, #GstAc3Parse
+ *
+ * This is a DCA (DTS Coherent Acoustics) parser.
+ *
+ * <refsect2>
+ * <title>Example launch line</title>
+ * |[
+ * gst-launch filesrc location=abc.dts ! dcaparse ! dtsdec ! audioresample ! audioconvert ! autoaudiosink
+ * ]|
+ * </refsect2>
+ */
+
+/* TODO:
+ * - should accept framed and unframed input (needs decodebin fixes first)
+ * - seeking in raw .dts files doesn't seem to work, but duration estimate ok
+ *
+ * - if frames have 'odd' durations, the frame durations (plus timestamps)
+ * aren't adjusted up occasionally to make up for rounding error gaps.
+ * (e.g. if 512 samples per frame @ 48kHz = 10.666666667 ms/frame)
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+
+#include "gstdcaparse.h"
+#include <gst/base/gstbytereader.h>
+#include <gst/base/gstbitreader.h>
+
+GST_DEBUG_CATEGORY_STATIC (dca_parse_debug);
+#define GST_CAT_DEFAULT dca_parse_debug
+
+static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS ("audio/x-dts,"
+ " framed = (boolean) true,"
+ " channels = (int) [ 1, 8 ],"
+ " rate = (int) [ 8000, 192000 ],"
+ " depth = (int) { 14, 16 },"
+ " endianness = (int) { LITTLE_ENDIAN, BIG_ENDIAN }"));
+
+static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS ("audio/x-dts, framed = (boolean) false"));
+
+static void gst_dca_parse_finalize (GObject * object);
+
+static gboolean gst_dca_parse_start (GstBaseParse * parse);
+static gboolean gst_dca_parse_stop (GstBaseParse * parse);
+static gboolean gst_dca_parse_check_valid_frame (GstBaseParse * parse,
+ GstBaseParseFrame * frame, guint * size, gint * skipsize);
+static GstFlowReturn gst_dca_parse_parse_frame (GstBaseParse * parse,
+ GstBaseParseFrame * frame);
+
+GST_BOILERPLATE (GstDcaParse, gst_dca_parse, GstBaseParse, GST_TYPE_BASE_PARSE);
+
+static void
+gst_dca_parse_base_init (gpointer klass)
+{
+ GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+
+ 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,
+ "DTS Coherent Acoustics audio stream parser", "Codec/Parser/Audio",
+ "DCA parser", "Tim-Philipp Müller <tim centricular net>");
+}
+
+static void
+gst_dca_parse_class_init (GstDcaParseClass * klass)
+{
+ GstBaseParseClass *parse_class = GST_BASE_PARSE_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ GST_DEBUG_CATEGORY_INIT (dca_parse_debug, "dcaparse", 0,
+ "DCA audio stream parser");
+
+ object_class->finalize = gst_dca_parse_finalize;
+
+ parse_class->start = GST_DEBUG_FUNCPTR (gst_dca_parse_start);
+ parse_class->stop = GST_DEBUG_FUNCPTR (gst_dca_parse_stop);
+ parse_class->check_valid_frame =
+ GST_DEBUG_FUNCPTR (gst_dca_parse_check_valid_frame);
+ parse_class->parse_frame = GST_DEBUG_FUNCPTR (gst_dca_parse_parse_frame);
+}
+
+static void
+gst_dca_parse_reset (GstDcaParse * dcaparse)
+{
+ dcaparse->channels = -1;
+ dcaparse->rate = -1;
+ dcaparse->depth = -1;
+ dcaparse->endianness = -1;
+ dcaparse->block_size = -1;
+ dcaparse->frame_size = -1;
+ dcaparse->last_sync = 0;
+}
+
+static void
+gst_dca_parse_init (GstDcaParse * dcaparse, GstDcaParseClass * klass)
+{
+ gst_base_parse_set_min_frame_size (GST_BASE_PARSE (dcaparse),
+ DCA_MIN_FRAMESIZE);
+ gst_dca_parse_reset (dcaparse);
+}
+
+static void
+gst_dca_parse_finalize (GObject * object)
+{
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static gboolean
+gst_dca_parse_start (GstBaseParse * parse)
+{
+ GstDcaParse *dcaparse = GST_DCA_PARSE (parse);
+
+ GST_DEBUG_OBJECT (parse, "starting");
+
+ gst_dca_parse_reset (dcaparse);
+
+ return TRUE;
+}
+
+static gboolean
+gst_dca_parse_stop (GstBaseParse * parse)
+{
+ GST_DEBUG_OBJECT (parse, "stopping");
+
+ return TRUE;
+}
+
+static gboolean
+gst_dca_parse_parse_header (GstDcaParse * dcaparse,
+ const GstByteReader * reader, guint * frame_size,
+ guint * sample_rate, guint * channels, guint * depth,
+ gint * endianness, guint * num_blocks, guint * samples_per_block,
+ gboolean * terminator)
+{
+ static const int sample_rates[16] = { 0, 8000, 16000, 32000, 0, 0, 11025,
+ 22050, 44100, 0, 0, 12000, 24000, 48000, 96000, 192000
+ };
+ static const guint8 channels_table[16] = { 1, 2, 2, 2, 2, 3, 3, 4, 4, 5,
+ 6, 6, 6, 7, 8, 8
+ };
+ GstByteReader r = *reader;
+ guint16 hdr[8];
+ guint32 marker;
+ guint chans, lfe, i;
+
+ if (gst_byte_reader_get_remaining (&r) < (4 + sizeof (hdr)))
+ return FALSE;
+
+ marker = gst_byte_reader_peek_uint32_be_unchecked (&r);
+
+ /* raw big endian or 14-bit big endian */
+ if (marker == 0x7FFE8001 || marker == 0x1FFFE800) {
+ for (i = 0; i < G_N_ELEMENTS (hdr); ++i)
+ hdr[i] = gst_byte_reader_get_uint16_be_unchecked (&r);
+ } else
+ /* raw little endian or 14-bit little endian */
+ if (marker == 0xFE7F0180 || marker == 0xFF1F00E8) {
+ for (i = 0; i < G_N_ELEMENTS (hdr); ++i)
+ hdr[i] = gst_byte_reader_get_uint16_le_unchecked (&r);
+ } else {
+ return FALSE;
+ }
+
+ GST_LOG_OBJECT (dcaparse, "dts sync marker 0x%08x at offset %u", marker,
+ gst_byte_reader_get_pos (reader));
+
+ /* 14-bit mode */
+ if (marker == 0x1FFFE800 || marker == 0xFF1F00E8) {
+ if ((hdr[2] & 0xFFF0) != 0x07F0)
+ return FALSE;
+ /* discard top 2 bits (2 void), shift in 2 */
+ hdr[0] = (hdr[0] << 2) | ((hdr[1] >> 12) & 0x0003);
+ /* discard top 4 bits (2 void, 2 shifted into hdr[0]), shift in 4 etc. */
+ hdr[1] = (hdr[1] << 4) | ((hdr[2] >> 10) & 0x000F);
+ hdr[2] = (hdr[2] << 6) | ((hdr[3] >> 8) & 0x003F);
+ hdr[3] = (hdr[3] << 8) | ((hdr[4] >> 6) & 0x00FF);
+ hdr[4] = (hdr[4] << 10) | ((hdr[5] >> 4) & 0x03FF);
+ hdr[5] = (hdr[5] << 12) | ((hdr[6] >> 2) & 0x0FFF);
+ hdr[6] = (hdr[6] << 14) | ((hdr[7] >> 0) & 0x3FFF);
+ g_assert (hdr[0] == 0x7FFE && hdr[1] == 0x8001);
+ }
+
+ GST_LOG_OBJECT (dcaparse, "frame header: %04x%04x%04x%04x",
+ hdr[2], hdr[3], hdr[4], hdr[5]);
+
+ *terminator = (hdr[2] & 0x80) ? FALSE : TRUE;
+ *samples_per_block = ((hdr[2] >> 10) & 0x1f) + 1;
+ *num_blocks = ((hdr[2] >> 2) & 0x7F) + 1;
+ *frame_size = (((hdr[2] & 0x03) << 12) | (hdr[3] >> 4)) + 1;
+ chans = ((hdr[3] & 0x0F) << 2) | (hdr[4] >> 14);
+ *sample_rate = sample_rates[(hdr[4] >> 10) & 0x0F];
+ lfe = (hdr[5] >> 9) & 0x03;
+
+ GST_TRACE_OBJECT (dcaparse, "frame size %u, num_blocks %u, rate %u, "
+ "samples per block %u", *frame_size, *num_blocks, *sample_rate,
+ *samples_per_block);
+
+ if (*num_blocks < 6 || *frame_size < 96 || *sample_rate == 0)
+ return FALSE;
+
+ if (marker == 0x1FFFE800 || marker == 0xFF1F00E8)
+ *frame_size = (*frame_size * 16) / 14; /* FIXME: round up? */
+
+ if (chans < G_N_ELEMENTS (channels_table))
+ *channels = channels_table[chans] + ((lfe) ? 1 : 0);
+ else
+ *channels = 0;
+
+ if (depth)
+ *depth = (marker == 0x1FFFE800 || marker == 0xFF1F00E8) ? 14 : 16;
+ if (endianness)
+ *endianness = (marker == 0xFE7F0180 || marker == 0xFF1F00E8) ?
+ G_LITTLE_ENDIAN : G_BIG_ENDIAN;
+
+ GST_TRACE_OBJECT (dcaparse, "frame size %u, channels %u, rate %u, "
+ "num_blocks %u, samples_per_block %u", *frame_size, *channels,
+ *sample_rate, *num_blocks, *samples_per_block);
+
+ return TRUE;
+}
+
+static gint
+gst_dca_parse_find_sync (GstDcaParse * dcaparse, GstByteReader * reader,
+ const GstBuffer * buf, guint32 * sync)
+{
+ guint32 best_sync = 0;
+ guint best_offset = G_MAXUINT;
+ gint off;
+
+ /* FIXME: verify syncs via _parse_header() here already */
+
+ /* Raw little endian */
+ off = gst_byte_reader_masked_scan_uint32 (reader, 0xffffffff, 0xfe7f0180,
+ 0, GST_BUFFER_SIZE (buf));
+ if (off >= 0 && off < best_offset) {
+ best_offset = off;
+ best_sync = 0xfe7f0180;
+ }
+
+ /* Raw big endian */
+ off = gst_byte_reader_masked_scan_uint32 (reader, 0xffffffff, 0x7ffe8001,
+ 0, GST_BUFFER_SIZE (buf));
+ if (off >= 0 && off < best_offset) {
+ best_offset = off;
+ best_sync = 0x7ffe8001;
+ }
+
+ /* FIXME: check next 2 bytes as well for 14-bit formats (but then don't
+ * forget to adjust the *skipsize= in _check_valid_frame() */
+
+ /* 14-bit little endian */
+ off = gst_byte_reader_masked_scan_uint32 (reader, 0xffffffff, 0xff1f00e8,
+ 0, GST_BUFFER_SIZE (buf));
+ if (off >= 0 && off < best_offset) {
+ best_offset = off;
+ best_sync = 0xff1f00e8;
+ }
+
+ /* 14-bit big endian */
+ off = gst_byte_reader_masked_scan_uint32 (reader, 0xffffffff, 0x1fffe800,
+ 0, GST_BUFFER_SIZE (buf));
+ if (off >= 0 && off < best_offset) {
+ best_offset = off;
+ best_sync = 0x1fffe800;
+ }
+
+ if (best_offset == G_MAXUINT)
+ return -1;
+
+ *sync = best_sync;
+ return best_offset;
+}
+
+static gboolean
+gst_dca_parse_check_valid_frame (GstBaseParse * parse,
+ GstBaseParseFrame * frame, guint * framesize, gint * skipsize)
+{
+ GstDcaParse *dcaparse = GST_DCA_PARSE (parse);
+ GstBuffer *buf = frame->buffer;
+ GstByteReader r = GST_BYTE_READER_INIT_FROM_BUFFER (buf);
+ gboolean parser_draining;
+ gboolean parser_in_sync;
+ gboolean terminator;
+ guint32 sync = 0;
+ guint size, rate, chans, num_blocks, samples_per_block;
+ gint off = -1;
+
+ if (G_UNLIKELY (GST_BUFFER_SIZE (buf) < 16))
+ return FALSE;
+
+ parser_in_sync = !GST_BASE_PARSE_LOST_SYNC (parse);
+
+ if (G_LIKELY (parser_in_sync && dcaparse->last_sync != 0)) {
+ off = gst_byte_reader_masked_scan_uint32 (&r, 0xffffffff,
+ dcaparse->last_sync, 0, GST_BUFFER_SIZE (buf));
+ }
+
+ if (G_UNLIKELY (off < 0)) {
+ off = gst_dca_parse_find_sync (dcaparse, &r, buf, &sync);
+ }
+
+ /* didn't find anything that looks like a sync word, skip */
+ if (off < 0) {
+ *skipsize = GST_BUFFER_SIZE (buf) - 3;
+ GST_DEBUG_OBJECT (dcaparse, "no sync, skipping %d bytes", *skipsize);
+ return FALSE;
+ }
+
+ GST_LOG_OBJECT (parse, "possible sync %08x at buffer offset %d", sync, off);
+
+ /* possible frame header, but not at offset 0? skip bytes before sync */
+ if (off > 0) {
+ *skipsize = off;
+ return FALSE;
+ }
+
+ /* make sure the values in the frame header look sane */
+ if (!gst_dca_parse_parse_header (dcaparse, &r, &size, &rate, &chans, NULL,
+ NULL, &num_blocks, &samples_per_block, &terminator)) {
+ *skipsize = 4;
+ return FALSE;
+ }
+
+ GST_LOG_OBJECT (parse, "got frame, sync %08x, size %u, rate %d, channels %d",
+ sync, size, rate, chans);
+
+ *framesize = size;
+
+ dcaparse->last_sync = sync;
+
+ parser_draining = GST_BASE_PARSE_DRAINING (parse);
+
+ if (!parser_in_sync && !parser_draining) {
+ /* check for second frame to be sure */
+ GST_DEBUG_OBJECT (dcaparse, "resyncing; checking next frame syncword");
+ if (GST_BUFFER_SIZE (buf) >= (size + 16)) {
+ guint s2, r2, c2, n2, s3;
+ gboolean t;
+
+ GST_MEMDUMP ("buf", GST_BUFFER_DATA (buf), size + 16);
+ gst_byte_reader_init_from_buffer (&r, buf);
+ gst_byte_reader_skip_unchecked (&r, size);
+
+ if (!gst_dca_parse_parse_header (dcaparse, &r, &s2, &r2, &c2, NULL, NULL,
+ &n2, &s3, &t)) {
+ GST_DEBUG_OBJECT (dcaparse, "didn't find second syncword");
+ *skipsize = 4;
+ return FALSE;
+ }
+
+ /* ok, got sync now, let's assume constant frame size */
+ gst_base_parse_set_min_frame_size (parse, size);
+ } else {
+ /* FIXME: baseparse always seems to hand us buffers of min_frame_size
+ * bytes, which is unhelpful here */
+ GST_LOG_OBJECT (dcaparse, "next sync out of reach (%u < %u)",
+ GST_BUFFER_SIZE (buf), size + 16);
+ /* *skipsize = 0; */
+ /* return FALSE; */
+ }
+ }
+
+ return TRUE;
+}
+
+static GstFlowReturn
+gst_dca_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
+{
+ GstDcaParse *dcaparse = GST_DCA_PARSE (parse);
+ GstBuffer *buf = frame->buffer;
+ GstByteReader r = GST_BYTE_READER_INIT_FROM_BUFFER (buf);
+ guint size, rate, chans, depth, block_size, num_blocks, samples_per_block;
+ gint endianness;
+ gboolean terminator;
+
+ if (!gst_dca_parse_parse_header (dcaparse, &r, &size, &rate, &chans, &depth,
+ &endianness, &num_blocks, &samples_per_block, &terminator))
+ goto broken_header;
+
+ block_size = num_blocks * samples_per_block;
+
+ if (G_UNLIKELY (dcaparse->rate != rate || dcaparse->channels != chans
+ || dcaparse->depth != depth || dcaparse->endianness != endianness
+ || (!terminator && dcaparse->block_size != block_size)
+ || (size != dcaparse->frame_size))) {
+ GstCaps *caps;
+
+ caps = gst_caps_new_simple ("audio/x-dts",
+ "framed", G_TYPE_BOOLEAN, TRUE,
+ "rate", G_TYPE_INT, rate, "channels", G_TYPE_INT, chans,
+ "endianness", G_TYPE_INT, endianness, "depth", G_TYPE_INT, depth,
+ "block-size", G_TYPE_INT, block_size, "frame-size", G_TYPE_INT, size,
+ NULL);
+ gst_buffer_set_caps (buf, caps);
+ gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (parse), caps);
+ gst_caps_unref (caps);
+
+ dcaparse->rate = rate;
+ dcaparse->channels = chans;
+ dcaparse->depth = depth;
+ dcaparse->endianness = endianness;
+ dcaparse->block_size = block_size;
+ dcaparse->frame_size = size;
+
+ gst_base_parse_set_frame_rate (parse, rate, block_size, 0, 0);
+ }
+
+ return GST_FLOW_OK;
+
+/* ERRORS */
+broken_header:
+ {
+ /* this really shouldn't ever happen */
+ GST_ELEMENT_ERROR (parse, STREAM, DECODE, (NULL), (NULL));
+ return GST_FLOW_ERROR;
+ }
+}
diff --git a/gst/audioparsers/gstdcaparse.h b/gst/audioparsers/gstdcaparse.h
new file mode 100644
index 000000000..b3e066bd0
--- /dev/null
+++ b/gst/audioparsers/gstdcaparse.h
@@ -0,0 +1,78 @@
+/* GStreamer DCA parser
+ * Copyright (C) 2010 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_DCA_PARSE_H__
+#define __GST_DCA_PARSE_H__
+
+#include <gst/gst.h>
+#include <gst/base/gstbaseparse.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_DCA_PARSE \
+ (gst_dca_parse_get_type())
+#define GST_DCA_PARSE(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_DCA_PARSE, GstDcaParse))
+#define GST_DCA_PARSE_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_DCA_PARSE, GstDcaParseClass))
+#define GST_IS_DCA_PARSE(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_DCA_PARSE))
+#define GST_IS_DCA_PARSE_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_DCA_PARSE))
+
+#define DCA_MIN_FRAMESIZE 96
+#define DCA_MAX_FRAMESIZE 18725 /* 16384*16/14 */
+
+typedef struct _GstDcaParse GstDcaParse;
+typedef struct _GstDcaParseClass GstDcaParseClass;
+
+/**
+ * GstDcaParse:
+ *
+ * The opaque GstDcaParse object
+ */
+struct _GstDcaParse {
+ GstBaseParse baseparse;
+
+ /*< private >*/
+ gint rate;
+ gint channels;
+ gint depth;
+ gint endianness;
+ gint block_size;
+ gint frame_size;
+
+ guint32 last_sync;
+};
+
+/**
+ * GstDcaParseClass:
+ * @parent_class: Element parent class.
+ *
+ * The opaque GstDcaParseClass data structure.
+ */
+struct _GstDcaParseClass {
+ GstBaseParseClass baseparse_class;
+};
+
+GType gst_dca_parse_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_DCA_PARSE_H__ */
diff --git a/gst/audioparsers/gstflacparse.c b/gst/audioparsers/gstflacparse.c
new file mode 100644
index 000000000..0249e88a2
--- /dev/null
+++ b/gst/audioparsers/gstflacparse.c
@@ -0,0 +1,1355 @@
+/* GStreamer
+ *
+ * Copyright (C) 2008 Sebastian Dröge <sebastian.droege@collabora.co.uk>.
+ * Copyright (C) 2009 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
+ * Copyright (C) 2009 Nokia Corporation. All rights reserved.
+ * Contact: Stefan Kost <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-flacparse
+ * @see_also: flacdec, oggdemux, vorbisparse
+ *
+ * The flacparse element will parse the header packets of the FLAC
+ * stream and put them as the streamheader in the caps. This is used in the
+ * multifdsink case where you want to stream live FLAC streams to multiple
+ * clients, each client has to receive the streamheaders first before they can
+ * consume the FLAC packets.
+ *
+ * This element also makes sure that the buffers that it pushes out are properly
+ * timestamped and that their offset and offset_end are set. The buffers that
+ * flacparse outputs have all of the metadata that oggmux expects to receive,
+ * which allows you to (for example) remux an ogg/flac or convert a native FLAC
+ * format file to an ogg bitstream.
+ *
+ * <refsect2>
+ * <title>Example pipelines</title>
+ * |[
+ * gst-launch -v filesrc location=sine.flac ! flacparse ! identity \
+ * ! oggmux ! filesink location=sine-remuxed.ogg
+ * ]| This pipeline converts a native FLAC format file to an ogg bitstream.
+ * It also illustrates that the streamheader is set in the caps, and that each
+ * buffer has the timestamp, duration, offset, and offset_end set.
+ * </refsect2>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "gstflacparse.h"
+
+#include <string.h>
+#include <gst/tag/tag.h>
+#include <gst/audio/audio.h>
+
+#include <gst/base/gstbitreader.h>
+#include <gst/base/gstbytereader.h>
+
+GST_DEBUG_CATEGORY_STATIC (flacparse_debug);
+#define GST_CAT_DEFAULT flacparse_debug
+
+/* CRC-8, poly = x^8 + x^2 + x^1 + x^0, init = 0 */
+static const guint8 crc8_table[256] = {
+ 0x00, 0x07, 0x0E, 0x09, 0x1C, 0x1B, 0x12, 0x15,
+ 0x38, 0x3F, 0x36, 0x31, 0x24, 0x23, 0x2A, 0x2D,
+ 0x70, 0x77, 0x7E, 0x79, 0x6C, 0x6B, 0x62, 0x65,
+ 0x48, 0x4F, 0x46, 0x41, 0x54, 0x53, 0x5A, 0x5D,
+ 0xE0, 0xE7, 0xEE, 0xE9, 0xFC, 0xFB, 0xF2, 0xF5,
+ 0xD8, 0xDF, 0xD6, 0xD1, 0xC4, 0xC3, 0xCA, 0xCD,
+ 0x90, 0x97, 0x9E, 0x99, 0x8C, 0x8B, 0x82, 0x85,
+ 0xA8, 0xAF, 0xA6, 0xA1, 0xB4, 0xB3, 0xBA, 0xBD,
+ 0xC7, 0xC0, 0xC9, 0xCE, 0xDB, 0xDC, 0xD5, 0xD2,
+ 0xFF, 0xF8, 0xF1, 0xF6, 0xE3, 0xE4, 0xED, 0xEA,
+ 0xB7, 0xB0, 0xB9, 0xBE, 0xAB, 0xAC, 0xA5, 0xA2,
+ 0x8F, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9D, 0x9A,
+ 0x27, 0x20, 0x29, 0x2E, 0x3B, 0x3C, 0x35, 0x32,
+ 0x1F, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0D, 0x0A,
+ 0x57, 0x50, 0x59, 0x5E, 0x4B, 0x4C, 0x45, 0x42,
+ 0x6F, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7D, 0x7A,
+ 0x89, 0x8E, 0x87, 0x80, 0x95, 0x92, 0x9B, 0x9C,
+ 0xB1, 0xB6, 0xBF, 0xB8, 0xAD, 0xAA, 0xA3, 0xA4,
+ 0xF9, 0xFE, 0xF7, 0xF0, 0xE5, 0xE2, 0xEB, 0xEC,
+ 0xC1, 0xC6, 0xCF, 0xC8, 0xDD, 0xDA, 0xD3, 0xD4,
+ 0x69, 0x6E, 0x67, 0x60, 0x75, 0x72, 0x7B, 0x7C,
+ 0x51, 0x56, 0x5F, 0x58, 0x4D, 0x4A, 0x43, 0x44,
+ 0x19, 0x1E, 0x17, 0x10, 0x05, 0x02, 0x0B, 0x0C,
+ 0x21, 0x26, 0x2F, 0x28, 0x3D, 0x3A, 0x33, 0x34,
+ 0x4E, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5C, 0x5B,
+ 0x76, 0x71, 0x78, 0x7F, 0x6A, 0x6D, 0x64, 0x63,
+ 0x3E, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2C, 0x2B,
+ 0x06, 0x01, 0x08, 0x0F, 0x1A, 0x1D, 0x14, 0x13,
+ 0xAE, 0xA9, 0xA0, 0xA7, 0xB2, 0xB5, 0xBC, 0xBB,
+ 0x96, 0x91, 0x98, 0x9F, 0x8A, 0x8D, 0x84, 0x83,
+ 0xDE, 0xD9, 0xD0, 0xD7, 0xC2, 0xC5, 0xCC, 0xCB,
+ 0xE6, 0xE1, 0xE8, 0xEF, 0xFA, 0xFD, 0xF4, 0xF3
+};
+
+static guint8
+gst_flac_calculate_crc8 (const guint8 * data, guint length)
+{
+ guint8 crc = 0;
+
+ while (length--) {
+ crc = crc8_table[crc ^ *data];
+ ++data;
+ }
+
+ return crc;
+}
+
+/* CRC-16, poly = x^16 + x^15 + x^2 + x^0, init = 0 */
+static const guint16 crc16_table[256] = {
+ 0x0000, 0x8005, 0x800f, 0x000a, 0x801b, 0x001e, 0x0014, 0x8011,
+ 0x8033, 0x0036, 0x003c, 0x8039, 0x0028, 0x802d, 0x8027, 0x0022,
+ 0x8063, 0x0066, 0x006c, 0x8069, 0x0078, 0x807d, 0x8077, 0x0072,
+ 0x0050, 0x8055, 0x805f, 0x005a, 0x804b, 0x004e, 0x0044, 0x8041,
+ 0x80c3, 0x00c6, 0x00cc, 0x80c9, 0x00d8, 0x80dd, 0x80d7, 0x00d2,
+ 0x00f0, 0x80f5, 0x80ff, 0x00fa, 0x80eb, 0x00ee, 0x00e4, 0x80e1,
+ 0x00a0, 0x80a5, 0x80af, 0x00aa, 0x80bb, 0x00be, 0x00b4, 0x80b1,
+ 0x8093, 0x0096, 0x009c, 0x8099, 0x0088, 0x808d, 0x8087, 0x0082,
+ 0x8183, 0x0186, 0x018c, 0x8189, 0x0198, 0x819d, 0x8197, 0x0192,
+ 0x01b0, 0x81b5, 0x81bf, 0x01ba, 0x81ab, 0x01ae, 0x01a4, 0x81a1,
+ 0x01e0, 0x81e5, 0x81ef, 0x01ea, 0x81fb, 0x01fe, 0x01f4, 0x81f1,
+ 0x81d3, 0x01d6, 0x01dc, 0x81d9, 0x01c8, 0x81cd, 0x81c7, 0x01c2,
+ 0x0140, 0x8145, 0x814f, 0x014a, 0x815b, 0x015e, 0x0154, 0x8151,
+ 0x8173, 0x0176, 0x017c, 0x8179, 0x0168, 0x816d, 0x8167, 0x0162,
+ 0x8123, 0x0126, 0x012c, 0x8129, 0x0138, 0x813d, 0x8137, 0x0132,
+ 0x0110, 0x8115, 0x811f, 0x011a, 0x810b, 0x010e, 0x0104, 0x8101,
+ 0x8303, 0x0306, 0x030c, 0x8309, 0x0318, 0x831d, 0x8317, 0x0312,
+ 0x0330, 0x8335, 0x833f, 0x033a, 0x832b, 0x032e, 0x0324, 0x8321,
+ 0x0360, 0x8365, 0x836f, 0x036a, 0x837b, 0x037e, 0x0374, 0x8371,
+ 0x8353, 0x0356, 0x035c, 0x8359, 0x0348, 0x834d, 0x8347, 0x0342,
+ 0x03c0, 0x83c5, 0x83cf, 0x03ca, 0x83db, 0x03de, 0x03d4, 0x83d1,
+ 0x83f3, 0x03f6, 0x03fc, 0x83f9, 0x03e8, 0x83ed, 0x83e7, 0x03e2,
+ 0x83a3, 0x03a6, 0x03ac, 0x83a9, 0x03b8, 0x83bd, 0x83b7, 0x03b2,
+ 0x0390, 0x8395, 0x839f, 0x039a, 0x838b, 0x038e, 0x0384, 0x8381,
+ 0x0280, 0x8285, 0x828f, 0x028a, 0x829b, 0x029e, 0x0294, 0x8291,
+ 0x82b3, 0x02b6, 0x02bc, 0x82b9, 0x02a8, 0x82ad, 0x82a7, 0x02a2,
+ 0x82e3, 0x02e6, 0x02ec, 0x82e9, 0x02f8, 0x82fd, 0x82f7, 0x02f2,
+ 0x02d0, 0x82d5, 0x82df, 0x02da, 0x82cb, 0x02ce, 0x02c4, 0x82c1,
+ 0x8243, 0x0246, 0x024c, 0x8249, 0x0258, 0x825d, 0x8257, 0x0252,
+ 0x0270, 0x8275, 0x827f, 0x027a, 0x826b, 0x026e, 0x0264, 0x8261,
+ 0x0220, 0x8225, 0x822f, 0x022a, 0x823b, 0x023e, 0x0234, 0x8231,
+ 0x8213, 0x0216, 0x021c, 0x8219, 0x0208, 0x820d, 0x8207, 0x0202
+};
+
+static guint16
+gst_flac_calculate_crc16 (const guint8 * data, guint length)
+{
+ guint16 crc = 0;
+
+ while (length--) {
+ crc = ((crc << 8) ^ crc16_table[(crc >> 8) ^ *data]) & 0xffff;
+ data++;
+ }
+
+ return crc;
+}
+
+enum
+{
+ PROP_0,
+ PROP_CHECK_FRAME_CHECKSUMS
+};
+
+#define DEFAULT_CHECK_FRAME_CHECKSUMS FALSE
+
+static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS ("audio/x-flac, framed = (boolean) true, "
+ "channels = (int) [ 1, 8 ], " "rate = (int) [ 1, 655350 ]")
+ );
+
+static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS ("audio/x-flac, framed = (boolean) false")
+ );
+
+static void gst_flac_parse_finalize (GObject * object);
+static void gst_flac_parse_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec);
+static void gst_flac_parse_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec);
+
+static gboolean gst_flac_parse_start (GstBaseParse * parse);
+static gboolean gst_flac_parse_stop (GstBaseParse * parse);
+static gboolean gst_flac_parse_check_valid_frame (GstBaseParse * parse,
+ GstBaseParseFrame * frame, guint * framesize, gint * skipsize);
+static GstFlowReturn gst_flac_parse_parse_frame (GstBaseParse * parse,
+ GstBaseParseFrame * frame);
+static GstFlowReturn gst_flac_parse_pre_push_frame (GstBaseParse * parse,
+ GstBaseParseFrame * frame);
+
+GST_BOILERPLATE (GstFlacParse, gst_flac_parse, GstBaseParse,
+ GST_TYPE_BASE_PARSE);
+
+static void
+gst_flac_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 (&src_factory));
+ gst_element_class_add_pad_template (element_class,
+ gst_static_pad_template_get (&sink_factory));
+
+ gst_element_class_set_details_simple (element_class, "FLAC audio parser",
+ "Codec/Parser/Audio",
+ "Parses audio with the FLAC lossless audio codec",
+ "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
+
+ GST_DEBUG_CATEGORY_INIT (flacparse_debug, "flacparse", 0,
+ "Flac parser element");
+}
+
+static void
+gst_flac_parse_class_init (GstFlacParseClass * klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GstBaseParseClass *baseparse_class = GST_BASE_PARSE_CLASS (klass);
+
+ gobject_class->finalize = gst_flac_parse_finalize;
+ gobject_class->set_property = gst_flac_parse_set_property;
+ gobject_class->get_property = gst_flac_parse_get_property;
+
+ g_object_class_install_property (gobject_class, PROP_CHECK_FRAME_CHECKSUMS,
+ g_param_spec_boolean ("check-frame-checksums", "Check Frame Checksums",
+ "Check the overall checksums of every frame",
+ DEFAULT_CHECK_FRAME_CHECKSUMS,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ baseparse_class->start = GST_DEBUG_FUNCPTR (gst_flac_parse_start);
+ baseparse_class->stop = GST_DEBUG_FUNCPTR (gst_flac_parse_stop);
+ baseparse_class->check_valid_frame =
+ GST_DEBUG_FUNCPTR (gst_flac_parse_check_valid_frame);
+ baseparse_class->parse_frame = GST_DEBUG_FUNCPTR (gst_flac_parse_parse_frame);
+ baseparse_class->pre_push_frame =
+ GST_DEBUG_FUNCPTR (gst_flac_parse_pre_push_frame);
+}
+
+static void
+gst_flac_parse_init (GstFlacParse * flacparse, GstFlacParseClass * klass)
+{
+ flacparse->check_frame_checksums = DEFAULT_CHECK_FRAME_CHECKSUMS;
+}
+
+static void
+gst_flac_parse_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec)
+{
+ GstFlacParse *flacparse = GST_FLAC_PARSE (object);
+
+ switch (prop_id) {
+ case PROP_CHECK_FRAME_CHECKSUMS:
+ flacparse->check_frame_checksums = g_value_get_boolean (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_flac_parse_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec)
+{
+ GstFlacParse *flacparse = GST_FLAC_PARSE (object);
+
+ switch (prop_id) {
+ case PROP_CHECK_FRAME_CHECKSUMS:
+ g_value_set_boolean (value, flacparse->check_frame_checksums);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_flac_parse_finalize (GObject * object)
+{
+ GstFlacParse *flacparse = GST_FLAC_PARSE (object);
+
+ if (flacparse->tags) {
+ gst_tag_list_free (flacparse->tags);
+ flacparse->tags = NULL;
+ }
+
+ g_list_foreach (flacparse->headers, (GFunc) gst_mini_object_unref, NULL);
+ g_list_free (flacparse->headers);
+ flacparse->headers = NULL;
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static gboolean
+gst_flac_parse_start (GstBaseParse * parse)
+{
+ GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
+
+ flacparse->state = GST_FLAC_PARSE_STATE_INIT;
+ flacparse->min_blocksize = 0;
+ flacparse->max_blocksize = 0;
+ flacparse->min_framesize = 0;
+ flacparse->max_framesize = 0;
+
+ flacparse->upstream_length = -1;
+
+ flacparse->samplerate = 0;
+ flacparse->channels = 0;
+ flacparse->bps = 0;
+ flacparse->total_samples = 0;
+
+ flacparse->offset = GST_CLOCK_TIME_NONE;
+ flacparse->blocking_strategy = 0;
+ flacparse->block_size = 0;
+ flacparse->sample_number = 0;
+
+ /* "fLaC" marker */
+ gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), 4);
+
+ /* inform baseclass we can come up with ts, based on counters in packets */
+ gst_base_parse_set_has_timing_info (GST_BASE_PARSE_CAST (flacparse), TRUE);
+ gst_base_parse_set_syncable (GST_BASE_PARSE_CAST (flacparse), TRUE);
+
+ return TRUE;
+}
+
+static gboolean
+gst_flac_parse_stop (GstBaseParse * parse)
+{
+ GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
+
+ if (flacparse->tags) {
+ gst_tag_list_free (flacparse->tags);
+ flacparse->tags = NULL;
+ }
+
+ g_list_foreach (flacparse->headers, (GFunc) gst_mini_object_unref, NULL);
+ g_list_free (flacparse->headers);
+ flacparse->headers = NULL;
+
+ return TRUE;
+}
+
+static const guint8 sample_size_table[] = { 0, 8, 12, 0, 16, 20, 24, 0 };
+
+static const guint16 blocksize_table[16] = {
+ 0, 192, 576 << 0, 576 << 1, 576 << 2, 576 << 3, 0, 0,
+ 256 << 0, 256 << 1, 256 << 2, 256 << 3, 256 << 4, 256 << 5, 256 << 6,
+ 256 << 7,
+};
+
+static const guint32 sample_rate_table[16] = {
+ 0,
+ 88200, 176400, 192000,
+ 8000, 16000, 22050, 24000, 32000, 44100, 48000, 96000,
+ 0, 0, 0, 0,
+};
+
+typedef enum
+{
+ FRAME_HEADER_VALID,
+ FRAME_HEADER_INVALID,
+ FRAME_HEADER_MORE_DATA
+} FrameHeaderCheckReturn;
+
+static FrameHeaderCheckReturn
+gst_flac_parse_frame_header_is_valid (GstFlacParse * flacparse,
+ const guint8 * data, guint size, gboolean set, guint16 * block_size_ret)
+{
+ GstBitReader reader = GST_BIT_READER_INIT (data, size);
+ guint8 blocking_strategy;
+ guint16 block_size;
+ guint32 samplerate = 0;
+ guint64 sample_number;
+ guint8 channels, bps;
+ guint8 tmp = 0;
+ guint8 actual_crc, expected_crc = 0;
+
+ /* Skip 14 bit sync code */
+ gst_bit_reader_skip_unchecked (&reader, 14);
+
+ /* Must be 0 */
+ if (gst_bit_reader_get_bits_uint8_unchecked (&reader, 1) != 0)
+ goto error;
+
+ /* 0 == fixed block size, 1 == variable block size */
+ blocking_strategy = gst_bit_reader_get_bits_uint8_unchecked (&reader, 1);
+
+ /* block size index, calculation of the real blocksize below */
+ block_size = gst_bit_reader_get_bits_uint16_unchecked (&reader, 4);
+ if (block_size == 0)
+ goto error;
+
+ /* sample rate index, calculation of the real samplerate below */
+ samplerate = gst_bit_reader_get_bits_uint16_unchecked (&reader, 4);
+ if (samplerate == 0x0f)
+ goto error;
+
+ /* channel assignment */
+ channels = gst_bit_reader_get_bits_uint8_unchecked (&reader, 4);
+ if (channels < 8) {
+ channels++;
+ } else if (channels <= 10) {
+ channels = 2;
+ } else if (channels > 10) {
+ goto error;
+ }
+ if (flacparse->channels && flacparse->channels != channels)
+ goto error;
+
+ /* bits per sample */
+ bps = gst_bit_reader_get_bits_uint8_unchecked (&reader, 3);
+ if (bps == 0x03 || bps == 0x07) {
+ goto error;
+ } else if (bps == 0 && flacparse->bps == 0) {
+ goto need_streaminfo;
+ }
+ bps = sample_size_table[bps];
+ if (flacparse->bps && bps != flacparse->bps)
+ goto error;
+
+ /* reserved, must be 0 */
+ if (gst_bit_reader_get_bits_uint8_unchecked (&reader, 1) != 0)
+ goto error;
+
+ /* read "utf8" encoded sample/frame number */
+ {
+ gint len = 0;
+
+ len = gst_bit_reader_get_bits_uint8_unchecked (&reader, 8);
+
+ /* This is slightly faster than a loop */
+ if (!(len & 0x80)) {
+ sample_number = len;
+ len = 0;
+ } else if ((len & 0xc0) && !(len & 0x20)) {
+ sample_number = len & 0x1f;
+ len = 1;
+ } else if ((len & 0xe0) && !(len & 0x10)) {
+ sample_number = len & 0x0f;
+ len = 2;
+ } else if ((len & 0xf0) && !(len & 0x08)) {
+ sample_number = len & 0x07;
+ len = 3;
+ } else if ((len & 0xf8) && !(len & 0x04)) {
+ sample_number = len & 0x03;
+ len = 4;
+ } else if ((len & 0xfc) && !(len & 0x02)) {
+ sample_number = len & 0x01;
+ len = 5;
+ } else if ((len & 0xfe) && !(len & 0x01)) {
+ sample_number = len & 0x0;
+ len = 6;
+ } else {
+ goto error;
+ }
+
+ if ((blocking_strategy == 0 && len > 5) ||
+ (blocking_strategy == 1 && len > 6))
+ goto error;
+
+ while (len > 0) {
+ if (!gst_bit_reader_get_bits_uint8 (&reader, &tmp, 8))
+ goto need_more_data;
+
+ if ((tmp & 0xc0) != 0x80)
+ goto error;
+
+ sample_number <<= 6;
+ sample_number |= (tmp & 0x3f);
+ len--;
+ }
+ }
+
+ /* calculate real blocksize from the blocksize index */
+ if (block_size == 0) {
+ goto error;
+ } else if (block_size == 6) {
+ if (!gst_bit_reader_get_bits_uint16 (&reader, &block_size, 8))
+ goto need_more_data;
+ block_size++;
+ } else if (block_size == 7) {
+ if (!gst_bit_reader_get_bits_uint16 (&reader, &block_size, 16))
+ goto need_more_data;
+ block_size++;
+ } else {
+ block_size = blocksize_table[block_size];
+ }
+
+ /* calculate the real samplerate from the samplerate index */
+ if (samplerate == 0 && flacparse->samplerate == 0) {
+ goto need_streaminfo;
+ } else if (samplerate < 12) {
+ samplerate = sample_rate_table[samplerate];
+ } else if (samplerate == 12) {
+ if (!gst_bit_reader_get_bits_uint32 (&reader, &samplerate, 8))
+ goto need_more_data;
+ samplerate *= 1000;
+ } else if (samplerate == 13) {
+ if (!gst_bit_reader_get_bits_uint32 (&reader, &samplerate, 16))
+ goto need_more_data;
+ } else if (samplerate == 14) {
+ if (!gst_bit_reader_get_bits_uint32 (&reader, &samplerate, 16))
+ goto need_more_data;
+ samplerate *= 10;
+ }
+
+ if (flacparse->samplerate && flacparse->samplerate != samplerate)
+ goto error;
+
+ /* check crc-8 for the header */
+ if (!gst_bit_reader_get_bits_uint8 (&reader, &expected_crc, 8))
+ goto need_more_data;
+
+ actual_crc =
+ gst_flac_calculate_crc8 (data,
+ (gst_bit_reader_get_pos (&reader) / 8) - 1);
+ if (actual_crc != expected_crc)
+ goto error;
+
+ if (set) {
+ flacparse->block_size = block_size;
+ if (!flacparse->samplerate)
+ flacparse->samplerate = samplerate;
+ if (!flacparse->bps)
+ flacparse->bps = bps;
+ if (!flacparse->blocking_strategy)
+ flacparse->blocking_strategy = blocking_strategy;
+ if (!flacparse->channels)
+ flacparse->channels = channels;
+ if (!flacparse->sample_number)
+ flacparse->sample_number = sample_number;
+
+ GST_DEBUG_OBJECT (flacparse,
+ "Parsed frame at offset %" G_GUINT64_FORMAT ":\n" "Block size: %u\n"
+ "Sample/Frame number: %" G_GUINT64_FORMAT, flacparse->offset,
+ flacparse->block_size, flacparse->sample_number);
+ }
+
+ if (block_size_ret)
+ *block_size_ret = block_size;
+
+ return FRAME_HEADER_VALID;
+
+need_streaminfo:
+ GST_ERROR_OBJECT (flacparse, "Need STREAMINFO");
+ return FRAME_HEADER_INVALID;
+error:
+ return FRAME_HEADER_INVALID;
+
+need_more_data:
+ return FRAME_HEADER_MORE_DATA;
+}
+
+static gboolean
+gst_flac_parse_frame_is_valid (GstFlacParse * flacparse,
+ GstBaseParseFrame * frame, guint * ret)
+{
+ GstBuffer *buffer;
+ const guint8 *data;
+ guint max, size, remaining;
+ guint i, search_start, search_end;
+ FrameHeaderCheckReturn header_ret;
+ guint16 block_size;
+
+ buffer = frame->buffer;
+ data = GST_BUFFER_DATA (buffer);
+ size = GST_BUFFER_SIZE (buffer);
+
+ if (size <= flacparse->min_framesize)
+ goto need_more;
+
+ header_ret =
+ gst_flac_parse_frame_header_is_valid (flacparse, data, size, TRUE,
+ &block_size);
+ if (header_ret == FRAME_HEADER_INVALID) {
+ *ret = 0;
+ return FALSE;
+ } else if (header_ret == FRAME_HEADER_MORE_DATA) {
+ goto need_more;
+ }
+
+ /* mind unknown framesize */
+ search_start = MAX (2, flacparse->min_framesize);
+ if (flacparse->max_framesize)
+ search_end = MIN (size, flacparse->max_framesize + 9 + 2);
+ else
+ search_end = size;
+ search_end -= 2;
+
+ remaining = size;
+
+ for (i = search_start; i < search_end; i++, remaining--) {
+ if ((GST_READ_UINT16_BE (data + i) & 0xfffe) == 0xfff8) {
+ header_ret =
+ gst_flac_parse_frame_header_is_valid (flacparse, data + i, remaining,
+ FALSE, NULL);
+ if (header_ret == FRAME_HEADER_VALID) {
+ if (flacparse->check_frame_checksums) {
+ guint16 actual_crc = gst_flac_calculate_crc16 (data, i - 2);
+ guint16 expected_crc = GST_READ_UINT16_BE (data + i - 2);
+
+ if (actual_crc != expected_crc)
+ continue;
+ }
+ *ret = i;
+ flacparse->block_size = block_size;
+ return TRUE;
+ } else if (header_ret == FRAME_HEADER_MORE_DATA) {
+ goto need_more;
+ }
+ }
+ }
+
+ /* For the last frame output everything to the end */
+ if (G_UNLIKELY (GST_BASE_PARSE_DRAINING (flacparse))) {
+ if (flacparse->check_frame_checksums) {
+ guint16 actual_crc = gst_flac_calculate_crc16 (data, size - 2);
+ guint16 expected_crc = GST_READ_UINT16_BE (data + size - 2);
+
+ if (actual_crc == expected_crc) {
+ *ret = size;
+ flacparse->block_size = block_size;
+ return TRUE;
+ }
+ } else {
+ *ret = size;
+ flacparse->block_size = block_size;
+ return TRUE;
+ }
+ }
+
+need_more:
+ max = flacparse->max_framesize + 16;
+ if (max == 16)
+ max = 1 << 24;
+ *ret = MIN (size + 4096, max);
+ return FALSE;
+}
+
+static gboolean
+gst_flac_parse_check_valid_frame (GstBaseParse * parse,
+ GstBaseParseFrame * frame, guint * framesize, gint * skipsize)
+{
+ GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
+ GstBuffer *buffer = frame->buffer;
+ const guint8 *data = GST_BUFFER_DATA (buffer);
+
+ if (G_UNLIKELY (GST_BUFFER_SIZE (buffer) < 4))
+ return FALSE;
+
+ if (flacparse->state == GST_FLAC_PARSE_STATE_INIT) {
+ if (memcmp (GST_BUFFER_DATA (buffer), "fLaC", 4) == 0) {
+ GST_DEBUG_OBJECT (flacparse, "fLaC marker found");
+ *framesize = 4;
+ return TRUE;
+ } else if (data[0] == 0xff && (data[1] >> 2) == 0x3e) {
+ GST_DEBUG_OBJECT (flacparse, "Found headerless FLAC");
+ /* Minimal size of a frame header */
+ gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), 9);
+ flacparse->state = GST_FLAC_PARSE_STATE_GENERATE_HEADERS;
+ *skipsize = 0;
+ return FALSE;
+ } else {
+ GST_DEBUG_OBJECT (flacparse, "fLaC marker not found");
+ return FALSE;
+ }
+ } else if (flacparse->state == GST_FLAC_PARSE_STATE_HEADERS) {
+ guint size = 4 + ((data[1] << 16) | (data[2] << 8) | (data[3]));
+
+ GST_DEBUG_OBJECT (flacparse, "Found metadata block of size %u", size);
+ *framesize = size;
+ return TRUE;
+ } else {
+ if ((GST_READ_UINT16_BE (data) & 0xfffe) == 0xfff8) {
+ gboolean ret;
+ guint next;
+
+ flacparse->offset = GST_BUFFER_OFFSET (buffer);
+ flacparse->blocking_strategy = 0;
+ flacparse->block_size = 0;
+ flacparse->sample_number = 0;
+
+ GST_DEBUG_OBJECT (flacparse, "Found sync code");
+ ret = gst_flac_parse_frame_is_valid (flacparse, frame, &next);
+ if (ret) {
+ *framesize = next;
+ return TRUE;
+ } else {
+ /* If we're at EOS and the frame was not valid, drop it! */
+ if (G_UNLIKELY (GST_BASE_PARSE_DRAINING (flacparse))) {
+ GST_WARNING_OBJECT (flacparse, "EOS");
+ return FALSE;
+ }
+
+ if (next == 0) {
+ } else if (next > GST_BUFFER_SIZE (buffer)) {
+ GST_DEBUG_OBJECT (flacparse, "Requesting %u bytes", next);
+ *skipsize = 0;
+ gst_base_parse_set_min_frame_size (parse, next);
+ return FALSE;
+ } else {
+ GST_ERROR_OBJECT (flacparse,
+ "Giving up on invalid frame (%d bytes)",
+ GST_BUFFER_SIZE (buffer));
+ return FALSE;
+ }
+ }
+ } else {
+ GstByteReader reader = GST_BYTE_READER_INIT_FROM_BUFFER (buffer);
+ gint off;
+
+ off =
+ gst_byte_reader_masked_scan_uint32 (&reader, 0xfffc0000, 0xfff80000,
+ 0, GST_BUFFER_SIZE (buffer));
+
+ if (off > 0) {
+ GST_DEBUG_OBJECT (parse, "Possible sync at buffer offset %d", off);
+ *skipsize = off;
+ return FALSE;
+ } else {
+ GST_DEBUG_OBJECT (flacparse, "Sync code not found");
+ *skipsize = GST_BUFFER_SIZE (buffer) - 3;
+ return FALSE;
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+static gboolean
+gst_flac_parse_handle_streaminfo (GstFlacParse * flacparse, GstBuffer * buffer)
+{
+ GstBitReader reader = GST_BIT_READER_INIT_FROM_BUFFER (buffer);
+
+ if (GST_BUFFER_SIZE (buffer) != 4 + 34) {
+ GST_ERROR_OBJECT (flacparse, "Invalid metablock size for STREAMINFO: %u",
+ GST_BUFFER_SIZE (buffer));
+ return FALSE;
+ }
+
+ /* Skip metadata block header */
+ gst_bit_reader_skip (&reader, 32);
+
+ if (!gst_bit_reader_get_bits_uint16 (&reader, &flacparse->min_blocksize, 16))
+ goto error;
+ if (flacparse->min_blocksize < 16) {
+ GST_ERROR_OBJECT (flacparse, "Invalid minimum block size: %u",
+ flacparse->min_blocksize);
+ return FALSE;
+ }
+
+ if (!gst_bit_reader_get_bits_uint16 (&reader, &flacparse->max_blocksize, 16))
+ goto error;
+ if (flacparse->max_blocksize < 16) {
+ GST_ERROR_OBJECT (flacparse, "Invalid maximum block size: %u",
+ flacparse->max_blocksize);
+ return FALSE;
+ }
+
+ if (!gst_bit_reader_get_bits_uint32 (&reader, &flacparse->min_framesize, 24))
+ goto error;
+ if (!gst_bit_reader_get_bits_uint32 (&reader, &flacparse->max_framesize, 24))
+ goto error;
+
+ if (!gst_bit_reader_get_bits_uint32 (&reader, &flacparse->samplerate, 20))
+ goto error;
+ if (flacparse->samplerate == 0) {
+ GST_ERROR_OBJECT (flacparse, "Invalid sample rate 0");
+ return FALSE;
+ }
+
+ if (!gst_bit_reader_get_bits_uint8 (&reader, &flacparse->channels, 3))
+ goto error;
+ flacparse->channels++;
+ if (flacparse->channels > 8) {
+ GST_ERROR_OBJECT (flacparse, "Invalid number of channels %u",
+ flacparse->channels);
+ return FALSE;
+ }
+
+ if (!gst_bit_reader_get_bits_uint8 (&reader, &flacparse->bps, 5))
+ goto error;
+ flacparse->bps++;
+
+ if (!gst_bit_reader_get_bits_uint64 (&reader, &flacparse->total_samples, 36))
+ goto error;
+ if (flacparse->total_samples)
+ gst_base_parse_set_duration (GST_BASE_PARSE (flacparse), GST_FORMAT_TIME,
+ GST_FRAMES_TO_CLOCK_TIME (flacparse->total_samples,
+ flacparse->samplerate), 0);
+
+ GST_DEBUG_OBJECT (flacparse, "STREAMINFO:\n"
+ "\tmin/max blocksize: %u/%u,\n"
+ "\tmin/max framesize: %u/%u,\n"
+ "\tsamplerate: %u,\n"
+ "\tchannels: %u,\n"
+ "\tbits per sample: %u,\n"
+ "\ttotal samples: %" G_GUINT64_FORMAT,
+ flacparse->min_blocksize, flacparse->max_blocksize,
+ flacparse->min_framesize, flacparse->max_framesize,
+ flacparse->samplerate,
+ flacparse->channels, flacparse->bps, flacparse->total_samples);
+
+ return TRUE;
+
+error:
+ GST_ERROR_OBJECT (flacparse, "Failed to read data");
+ return FALSE;
+}
+
+static gboolean
+gst_flac_parse_handle_vorbiscomment (GstFlacParse * flacparse,
+ GstBuffer * buffer)
+{
+ flacparse->tags = gst_tag_list_from_vorbiscomment_buffer (buffer,
+ GST_BUFFER_DATA (buffer), 4, NULL);
+
+ if (flacparse->tags == NULL) {
+ GST_ERROR_OBJECT (flacparse, "Invalid vorbiscomment block");
+ } else if (gst_tag_list_is_empty (flacparse->tags)) {
+ gst_tag_list_free (flacparse->tags);
+ flacparse->tags = NULL;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+gst_flac_parse_handle_picture (GstFlacParse * flacparse, GstBuffer * buffer)
+{
+ GstByteReader reader = GST_BYTE_READER_INIT_FROM_BUFFER (buffer);
+ const guint8 *data = GST_BUFFER_DATA (buffer);
+ guint32 img_len = 0, img_type = 0;
+ guint32 img_mimetype_len = 0, img_description_len = 0;
+
+ if (!gst_byte_reader_skip (&reader, 4))
+ goto error;
+
+ if (!gst_byte_reader_get_uint32_be (&reader, &img_type))
+ goto error;
+
+ if (!gst_byte_reader_get_uint32_be (&reader, &img_mimetype_len))
+ goto error;
+ if (!gst_byte_reader_skip (&reader, img_mimetype_len))
+ goto error;
+
+ if (!gst_byte_reader_get_uint32_be (&reader, &img_description_len))
+ goto error;
+ if (!gst_byte_reader_skip (&reader, img_description_len))
+ goto error;
+
+ if (!gst_byte_reader_skip (&reader, 4 * 4))
+ goto error;
+
+ if (!gst_byte_reader_get_uint32_be (&reader, &img_len))
+ goto error;
+
+ if (!flacparse->tags)
+ flacparse->tags = gst_tag_list_new ();
+
+ gst_tag_list_add_id3_image (flacparse->tags,
+ data + gst_byte_reader_get_pos (&reader), img_len, img_type);
+
+ if (gst_tag_list_is_empty (flacparse->tags)) {
+ gst_tag_list_free (flacparse->tags);
+ flacparse->tags = NULL;
+ }
+
+ return TRUE;
+
+error:
+ GST_ERROR_OBJECT (flacparse, "Error reading data");
+ return FALSE;
+}
+
+static gboolean
+gst_flac_parse_handle_seektable (GstFlacParse * flacparse, GstBuffer * buffer)
+{
+
+ GST_DEBUG_OBJECT (flacparse, "storing seektable");
+ /* only store for now;
+ * offset of the first frame is needed to get real info */
+ flacparse->seektable = gst_buffer_ref (buffer);
+
+ return TRUE;
+}
+
+static void
+gst_flac_parse_process_seektable (GstFlacParse * flacparse, gint64 boffset)
+{
+ GstByteReader br;
+ gint64 offset = 0, samples = 0;
+
+ GST_DEBUG_OBJECT (flacparse,
+ "parsing seektable; base offset %" G_GINT64_FORMAT, boffset);
+
+ if (boffset <= 0)
+ goto done;
+
+ gst_byte_reader_init_from_buffer (&br, flacparse->seektable);
+ /* skip header */
+ if (!gst_byte_reader_skip (&br, 4))
+ goto done;
+
+ /* seekpoints */
+ while (gst_byte_reader_get_remaining (&br)) {
+ if (!gst_byte_reader_get_int64_be (&br, &samples))
+ break;
+ if (!gst_byte_reader_get_int64_be (&br, &offset))
+ break;
+ if (!gst_byte_reader_skip (&br, 2))
+ break;
+
+ GST_LOG_OBJECT (flacparse, "samples %" G_GINT64_FORMAT " -> offset %"
+ G_GINT64_FORMAT, samples, offset);
+
+ /* sanity check */
+ if (G_LIKELY (offset > 0 && samples > 0)) {
+ gst_base_parse_add_index_entry (GST_BASE_PARSE (flacparse),
+ boffset + offset, gst_util_uint64_scale (samples, GST_SECOND,
+ flacparse->samplerate), TRUE, FALSE);
+ }
+ }
+
+done:
+ gst_buffer_unref (flacparse->seektable);
+ flacparse->seektable = NULL;
+}
+
+static void
+_value_array_append_buffer (GValue * array_val, GstBuffer * buf)
+{
+ GValue value = { 0, };
+
+ g_value_init (&value, GST_TYPE_BUFFER);
+ /* copy buffer to avoid problems with circular refcounts */
+ buf = gst_buffer_copy (buf);
+ /* again, for good measure */
+ GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_IN_CAPS);
+ gst_value_set_buffer (&value, buf);
+ gst_buffer_unref (buf);
+ gst_value_array_append_value (array_val, &value);
+ g_value_unset (&value);
+}
+
+static gboolean
+gst_flac_parse_handle_headers (GstFlacParse * flacparse)
+{
+ GstBuffer *vorbiscomment = NULL;
+ GstBuffer *streaminfo = NULL;
+ GstBuffer *marker = NULL;
+ GValue array = { 0, };
+ GstCaps *caps;
+ GList *l;
+ gboolean res = TRUE;
+
+ caps = gst_caps_new_simple ("audio/x-flac",
+ "channels", G_TYPE_INT, flacparse->channels,
+ "framed", G_TYPE_BOOLEAN, TRUE,
+ "rate", G_TYPE_INT, flacparse->samplerate, NULL);
+
+ if (!flacparse->headers)
+ goto push_headers;
+
+ for (l = flacparse->headers; l; l = l->next) {
+ GstBuffer *header = l->data;
+ const guint8 *data = GST_BUFFER_DATA (header);
+ guint size = GST_BUFFER_SIZE (header);
+
+ GST_BUFFER_FLAG_SET (header, GST_BUFFER_FLAG_IN_CAPS);
+
+ if (size == 4 && memcmp (data, "fLaC", 4) == 0) {
+ marker = header;
+ } else if (size > 1 && (data[0] & 0x7f) == 0) {
+ streaminfo = header;
+ } else if (size > 1 && (data[0] & 0x7f) == 4) {
+ vorbiscomment = header;
+ }
+ }
+
+ if (marker == NULL || streaminfo == NULL || vorbiscomment == NULL) {
+ GST_WARNING_OBJECT (flacparse,
+ "missing header %p %p %p, muxing into container "
+ "formats may be broken", marker, streaminfo, vorbiscomment);
+ goto push_headers;
+ }
+
+ g_value_init (&array, GST_TYPE_ARRAY);
+
+ /* add marker including STREAMINFO header */
+ {
+ GstBuffer *buf;
+ guint16 num;
+
+ /* minus one for the marker that is merged with streaminfo here */
+ num = g_list_length (flacparse->headers) - 1;
+
+ buf = gst_buffer_new_and_alloc (13 + GST_BUFFER_SIZE (streaminfo));
+ GST_BUFFER_DATA (buf)[0] = 0x7f;
+ memcpy (GST_BUFFER_DATA (buf) + 1, "FLAC", 4);
+ GST_BUFFER_DATA (buf)[5] = 0x01; /* mapping version major */
+ GST_BUFFER_DATA (buf)[6] = 0x00; /* mapping version minor */
+ GST_BUFFER_DATA (buf)[7] = (num & 0xFF00) >> 8;
+ GST_BUFFER_DATA (buf)[8] = (num & 0x00FF) >> 0;
+ memcpy (GST_BUFFER_DATA (buf) + 9, "fLaC", 4);
+ memcpy (GST_BUFFER_DATA (buf) + 13, GST_BUFFER_DATA (streaminfo),
+ GST_BUFFER_SIZE (streaminfo));
+ _value_array_append_buffer (&array, buf);
+ gst_buffer_unref (buf);
+ }
+
+ /* add VORBISCOMMENT header */
+ _value_array_append_buffer (&array, vorbiscomment);
+
+ /* add other headers, if there are any */
+ for (l = flacparse->headers; l; l = l->next) {
+ if (GST_BUFFER_CAST (l->data) != marker &&
+ GST_BUFFER_CAST (l->data) != streaminfo &&
+ GST_BUFFER_CAST (l->data) != vorbiscomment) {
+ _value_array_append_buffer (&array, GST_BUFFER_CAST (l->data));
+ }
+ }
+
+ gst_structure_set_value (gst_caps_get_structure (caps, 0),
+ "streamheader", &array);
+ g_value_unset (&array);
+
+push_headers:
+
+ gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (GST_BASE_PARSE (flacparse)), caps);
+ gst_caps_unref (caps);
+
+ /* push header buffers; update caps, so when we push the first buffer the
+ * negotiated caps will change to caps that include the streamheader field */
+ while (flacparse->headers) {
+ GstBuffer *buf = GST_BUFFER (flacparse->headers->data);
+ GstFlowReturn ret;
+ GstBaseParseFrame frame;
+
+ flacparse->headers =
+ g_list_delete_link (flacparse->headers, flacparse->headers);
+ buf = gst_buffer_make_metadata_writable (buf);
+ gst_buffer_set_caps (buf,
+ GST_PAD_CAPS (GST_BASE_PARSE_SRC_PAD (GST_BASE_PARSE (flacparse))));
+
+ /* init, set and give away frame */
+ gst_base_parse_frame_init (&frame);
+ frame.buffer = buf;
+ frame.overhead = -1;
+ ret = gst_base_parse_push_frame (GST_BASE_PARSE (flacparse), &frame);
+ if (ret != GST_FLOW_OK) {
+ res = FALSE;
+ break;
+ }
+ }
+ g_list_foreach (flacparse->headers, (GFunc) gst_mini_object_unref, NULL);
+ g_list_free (flacparse->headers);
+ flacparse->headers = NULL;
+
+ return res;
+}
+
+static gboolean
+gst_flac_parse_generate_headers (GstFlacParse * flacparse)
+{
+ GstBuffer *marker, *streaminfo, *vorbiscomment;
+ guint8 *data;
+
+ marker = gst_buffer_new_and_alloc (4);
+ memcpy (GST_BUFFER_DATA (marker), "fLaC", 4);
+ GST_BUFFER_TIMESTAMP (marker) = GST_CLOCK_TIME_NONE;
+ GST_BUFFER_DURATION (marker) = GST_CLOCK_TIME_NONE;
+ GST_BUFFER_OFFSET (marker) = 0;
+ GST_BUFFER_OFFSET_END (marker) = 0;
+ flacparse->headers = g_list_append (flacparse->headers, marker);
+
+ streaminfo = gst_buffer_new_and_alloc (4 + 34);
+ data = GST_BUFFER_DATA (streaminfo);
+ memset (data, 0, 4 + 34);
+
+ /* metadata block header */
+ data[0] = 0x00; /* is_last = 0; type = 0; */
+ data[1] = 0x00; /* length = 34; */
+ data[2] = 0x00;
+ data[3] = 0x22;
+
+ /* streaminfo */
+
+ data[4] = (flacparse->block_size >> 8) & 0xff; /* min blocksize = blocksize; */
+ data[5] = (flacparse->block_size) & 0xff;
+ data[6] = (flacparse->block_size >> 8) & 0xff; /* max blocksize = blocksize; */
+ data[7] = (flacparse->block_size) & 0xff;
+
+ data[8] = 0x00; /* min framesize = 0; */
+ data[9] = 0x00;
+ data[10] = 0x00;
+ data[11] = 0x00; /* max framesize = 0; */
+ data[12] = 0x00;
+ data[13] = 0x00;
+
+ data[14] = (flacparse->samplerate >> 12) & 0xff;
+ data[15] = (flacparse->samplerate >> 4) & 0xff;
+ data[16] = (flacparse->samplerate >> 0) & 0xf0;
+
+ data[16] |= (flacparse->channels - 1) << 1;
+
+ data[16] |= ((flacparse->bps - 1) >> 4) & 0x01;
+ data[17] = (((flacparse->bps - 1)) & 0x0f) << 4;
+
+ {
+ gint64 duration;
+ GstFormat fmt = GST_FORMAT_TIME;
+
+ if (gst_pad_query_peer_duration (GST_BASE_PARSE_SINK_PAD (GST_BASE_PARSE
+ (flacparse)), &fmt, &duration) && fmt == GST_FORMAT_TIME) {
+ duration = GST_CLOCK_TIME_TO_FRAMES (duration, flacparse->samplerate);
+
+ data[17] |= (duration >> 32) & 0xff;
+ data[18] |= (duration >> 24) & 0xff;
+ data[19] |= (duration >> 16) & 0xff;
+ data[20] |= (duration >> 8) & 0xff;
+ data[21] |= (duration >> 0) & 0xff;
+ }
+ }
+ /* MD5 = 0; */
+
+ GST_BUFFER_TIMESTAMP (streaminfo) = GST_CLOCK_TIME_NONE;
+ GST_BUFFER_DURATION (streaminfo) = GST_CLOCK_TIME_NONE;
+ GST_BUFFER_OFFSET (streaminfo) = 0;
+ GST_BUFFER_OFFSET_END (streaminfo) = 0;
+ flacparse->headers = g_list_append (flacparse->headers, streaminfo);
+
+ /* empty vorbiscomment */
+ {
+ GstTagList *taglist = gst_tag_list_new ();
+ guchar header[4];
+ guint size;
+
+ header[0] = 0x84; /* is_last = 1; type = 4; */
+
+ vorbiscomment =
+ gst_tag_list_to_vorbiscomment_buffer (taglist, header,
+ sizeof (header), NULL);
+ gst_tag_list_free (taglist);
+
+ /* Get rid of framing bit */
+ if (GST_BUFFER_DATA (vorbiscomment)[GST_BUFFER_SIZE (vorbiscomment) -
+ 1] == 1) {
+ GstBuffer *sub;
+
+ sub =
+ gst_buffer_create_sub (vorbiscomment, 0,
+ GST_BUFFER_SIZE (vorbiscomment) - 1);
+ gst_buffer_unref (vorbiscomment);
+ vorbiscomment = sub;
+ }
+
+ size = GST_BUFFER_SIZE (vorbiscomment) - 4;
+ GST_BUFFER_DATA (vorbiscomment)[1] = ((size & 0xFF0000) >> 16);
+ GST_BUFFER_DATA (vorbiscomment)[2] = ((size & 0x00FF00) >> 8);
+ GST_BUFFER_DATA (vorbiscomment)[3] = (size & 0x0000FF);
+
+ GST_BUFFER_TIMESTAMP (vorbiscomment) = GST_CLOCK_TIME_NONE;
+ GST_BUFFER_DURATION (vorbiscomment) = GST_CLOCK_TIME_NONE;
+ GST_BUFFER_OFFSET (vorbiscomment) = 0;
+ GST_BUFFER_OFFSET_END (vorbiscomment) = 0;
+ flacparse->headers = g_list_append (flacparse->headers, vorbiscomment);
+ }
+
+ return TRUE;
+}
+
+static GstFlowReturn
+gst_flac_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
+{
+ GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
+ GstBuffer *buffer = frame->buffer;
+ const guint8 *data = GST_BUFFER_DATA (buffer);
+
+ if (flacparse->state == GST_FLAC_PARSE_STATE_INIT) {
+ GST_BUFFER_TIMESTAMP (buffer) = GST_CLOCK_TIME_NONE;
+ GST_BUFFER_DURATION (buffer) = GST_CLOCK_TIME_NONE;
+ GST_BUFFER_OFFSET (buffer) = 0;
+ GST_BUFFER_OFFSET_END (buffer) = 0;
+
+ /* 32 bits metadata block */
+ gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), 4);
+ flacparse->state = GST_FLAC_PARSE_STATE_HEADERS;
+
+ flacparse->headers =
+ g_list_append (flacparse->headers, gst_buffer_ref (buffer));
+
+ return GST_BASE_PARSE_FLOW_DROPPED;
+ } else if (flacparse->state == GST_FLAC_PARSE_STATE_HEADERS) {
+ gboolean is_last = ((data[0] & 0x80) == 0x80);
+ guint type = (data[0] & 0x7F);
+
+ if (type == 127) {
+ GST_WARNING_OBJECT (flacparse, "Invalid metadata block type");
+ return GST_BASE_PARSE_FLOW_DROPPED;
+ }
+
+ GST_DEBUG_OBJECT (flacparse, "Handling metadata block of type %u", type);
+
+ switch (type) {
+ case 0: /* STREAMINFO */
+ if (!gst_flac_parse_handle_streaminfo (flacparse, buffer))
+ return GST_FLOW_ERROR;
+ break;
+ case 3: /* SEEKTABLE */
+ if (!gst_flac_parse_handle_seektable (flacparse, buffer))
+ return GST_FLOW_ERROR;
+ break;
+ case 4: /* VORBIS_COMMENT */
+ if (!gst_flac_parse_handle_vorbiscomment (flacparse, buffer))
+ return GST_FLOW_ERROR;
+ break;
+ case 6: /* PICTURE */
+ if (!gst_flac_parse_handle_picture (flacparse, buffer))
+ return GST_FLOW_ERROR;
+ break;
+ case 1: /* PADDING */
+ case 2: /* APPLICATION */
+ case 5: /* CUESHEET */
+ default: /* RESERVED */
+ break;
+ }
+
+ GST_BUFFER_TIMESTAMP (buffer) = GST_CLOCK_TIME_NONE;
+ GST_BUFFER_DURATION (buffer) = GST_CLOCK_TIME_NONE;
+ GST_BUFFER_OFFSET (buffer) = 0;
+ GST_BUFFER_OFFSET_END (buffer) = 0;
+
+ flacparse->headers =
+ g_list_append (flacparse->headers, gst_buffer_ref (buffer));
+
+ if (is_last) {
+ if (!gst_flac_parse_handle_headers (flacparse))
+ return GST_FLOW_ERROR;
+
+ /* Minimal size of a frame header */
+ gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), MAX (9,
+ flacparse->min_framesize));
+ flacparse->state = GST_FLAC_PARSE_STATE_DATA;
+ }
+
+ /* DROPPED because we pushed already or will push all headers manually */
+ return GST_BASE_PARSE_FLOW_DROPPED;
+ } else {
+ if (flacparse->offset != GST_BUFFER_OFFSET (buffer)) {
+ FrameHeaderCheckReturn ret;
+
+ flacparse->offset = GST_BUFFER_OFFSET (buffer);
+ ret =
+ gst_flac_parse_frame_header_is_valid (flacparse,
+ GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer), TRUE, NULL);
+ if (ret != FRAME_HEADER_VALID) {
+ GST_ERROR_OBJECT (flacparse,
+ "Baseclass didn't provide a complete frame");
+ return GST_FLOW_ERROR;
+ }
+ }
+
+ if (flacparse->block_size == 0) {
+ GST_ERROR_OBJECT (flacparse, "Unparsed frame");
+ return GST_FLOW_ERROR;
+ }
+
+ if (flacparse->seektable)
+ gst_flac_parse_process_seektable (flacparse, GST_BUFFER_OFFSET (buffer));
+
+ if (flacparse->state == GST_FLAC_PARSE_STATE_GENERATE_HEADERS) {
+ if (flacparse->blocking_strategy == 1) {
+ GST_WARNING_OBJECT (flacparse,
+ "Generating headers for variable blocksize streams not supported");
+
+ if (!gst_flac_parse_handle_headers (flacparse))
+ return GST_FLOW_ERROR;
+ } else {
+ GST_DEBUG_OBJECT (flacparse, "Generating headers");
+
+ if (!gst_flac_parse_generate_headers (flacparse))
+ return GST_FLOW_ERROR;
+
+ if (!gst_flac_parse_handle_headers (flacparse))
+ return GST_FLOW_ERROR;
+ }
+ flacparse->state = GST_FLAC_PARSE_STATE_DATA;
+ }
+
+ /* also cater for oggmux metadata */
+ if (flacparse->blocking_strategy == 0) {
+ GST_BUFFER_TIMESTAMP (buffer) =
+ gst_util_uint64_scale (flacparse->sample_number,
+ flacparse->block_size * GST_SECOND, flacparse->samplerate);
+ GST_BUFFER_OFFSET_END (buffer) =
+ flacparse->sample_number * flacparse->block_size +
+ flacparse->block_size;
+ } else {
+ GST_BUFFER_TIMESTAMP (buffer) =
+ gst_util_uint64_scale (flacparse->sample_number, GST_SECOND,
+ flacparse->samplerate);
+ GST_BUFFER_OFFSET_END (buffer) =
+ flacparse->sample_number + flacparse->block_size;
+ }
+ GST_BUFFER_OFFSET (buffer) =
+ gst_util_uint64_scale (GST_BUFFER_OFFSET_END (buffer), GST_SECOND,
+ flacparse->samplerate);
+ GST_BUFFER_DURATION (buffer) =
+ GST_BUFFER_OFFSET (buffer) - GST_BUFFER_TIMESTAMP (buffer);
+
+ /* To simplify, we just assume that it's a fixed size header and ignore
+ * subframe headers. The first could lead us to being off by 88 bits and
+ * the second even less, so the total inaccuracy is negligible. */
+ frame->overhead = 7;
+
+ /* Minimal size of a frame header */
+ gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), MAX (9,
+ flacparse->min_framesize));
+
+ flacparse->offset = -1;
+ flacparse->blocking_strategy = 0;
+ flacparse->block_size = 0;
+ flacparse->sample_number = 0;
+ return GST_FLOW_OK;
+ }
+}
+
+static GstFlowReturn
+gst_flac_parse_pre_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
+{
+ GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
+
+ /* Push tags */
+ if (flacparse->tags) {
+ gst_element_found_tags (GST_ELEMENT (flacparse), flacparse->tags);
+ flacparse->tags = NULL;
+ }
+
+ frame->flags |= GST_BASE_PARSE_FRAME_FLAG_CLIP;
+
+ return GST_FLOW_OK;
+}
diff --git a/gst/audioparsers/gstflacparse.h b/gst/audioparsers/gstflacparse.h
new file mode 100644
index 000000000..1c6db0e58
--- /dev/null
+++ b/gst/audioparsers/gstflacparse.h
@@ -0,0 +1,92 @@
+/* GStreamer
+ *
+ * Copyright (C) 2008 Sebastian Dröge <sebastian.droege@collabora.co.uk>.
+ * Copyright (C) 2009 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
+ * Copyright (C) 2009 Nokia Corporation. All rights reserved.
+ * Contact: Stefan Kost <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_FLAC_PARSE_H__
+#define __GST_FLAC_PARSE_H__
+
+#include <gst/gst.h>
+#include <gst/base/gstbaseparse.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_FLAC_PARSE (gst_flac_parse_get_type())
+#define GST_FLAC_PARSE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_FLAC_PARSE,GstFlacParse))
+#define GST_FLAC_PARSE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_FLAC_PARSE,GstFlacParseClass))
+#define GST_FLAC_PARSE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_FLAC_PARSE,GstFlacParseClass))
+#define GST_IS_FLAC_PARSE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_FLAC_PARSE))
+#define GST_IS_FLAC_PARSE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_FLAC_PARSE))
+#define GST_FLAC_PARSE_CAST(obj) ((GstFlacParse *)(obj))
+
+typedef struct _GstFlacParse GstFlacParse;
+typedef struct _GstFlacParseClass GstFlacParseClass;
+
+typedef enum {
+ GST_FLAC_PARSE_STATE_INIT,
+ GST_FLAC_PARSE_STATE_HEADERS,
+ GST_FLAC_PARSE_STATE_GENERATE_HEADERS,
+ GST_FLAC_PARSE_STATE_DATA
+} GstFlacParseState;
+
+typedef struct {
+ guint8 type;
+} GstFlacParseSubFrame;
+
+struct _GstFlacParse {
+ GstBaseParse parent;
+
+ /* Properties */
+ gboolean check_frame_checksums;
+
+ GstFlacParseState state;
+
+ gint64 upstream_length;
+
+ /* STREAMINFO content */
+ guint16 min_blocksize, max_blocksize;
+ guint32 min_framesize, max_framesize;
+ guint32 samplerate;
+ guint8 channels;
+ guint8 bps;
+ guint64 total_samples;
+
+ /* Current frame */
+ guint64 offset;
+ guint8 blocking_strategy;
+ guint16 block_size;
+ guint64 sample_number;
+
+ GstTagList *tags;
+
+ GList *headers;
+ GstBuffer *seektable;
+};
+
+struct _GstFlacParseClass {
+ GstBaseParseClass parent_class;
+};
+
+GType gst_flac_parse_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_FLAC_PARSE_H__ */
diff --git a/gst/audioparsers/gstmpegaudioparse.c b/gst/audioparsers/gstmpegaudioparse.c
new file mode 100644
index 000000000..0c55704a9
--- /dev/null
+++ b/gst/audioparsers/gstmpegaudioparse.c
@@ -0,0 +1,1265 @@
+/* GStreamer MPEG audio parser
+ * Copyright (C) 2006-2007 Jan Schmidt <thaytan@mad.scientist.com>
+ * Copyright (C) 2010 Mark Nauwelaerts <mnauw users sf net>
+ * Copyright (C) 2010 Nokia Corporation. All rights reserved.
+ * Contact: Stefan Kost <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-mpegaudioparse
+ * @short_description: MPEG audio parser
+ * @see_also: #GstAmrParse, #GstAACParse
+ *
+ * Parses and frames mpeg1 audio streams. Provides seeking.
+ *
+ * <refsect2>
+ * <title>Example launch line</title>
+ * |[
+ * gst-launch filesrc location=test.mp3 ! mpegaudioparse ! mad ! autoaudiosink
+ * ]|
+ * </refsect2>
+ */
+
+/* FIXME: we should make the base class (GstBaseParse) aware of the
+ * XING seek table somehow, so it can use it properly for things like
+ * accurate seeks. Currently it can only do a lookup via the convert function,
+ * but then doesn't know what the result represents exactly. One could either
+ * add a vfunc for index lookup, or just make mpegaudioparse populate the
+ * base class's index via the API provided.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+
+#include "gstmpegaudioparse.h"
+#include <gst/base/gstbytereader.h>
+
+GST_DEBUG_CATEGORY_STATIC (mpeg_audio_parse_debug);
+#define GST_CAT_DEFAULT mpeg_audio_parse_debug
+
+#define MPEG_AUDIO_CHANNEL_MODE_UNKNOWN -1
+#define MPEG_AUDIO_CHANNEL_MODE_STEREO 0
+#define MPEG_AUDIO_CHANNEL_MODE_JOINT_STEREO 1
+#define MPEG_AUDIO_CHANNEL_MODE_DUAL_CHANNEL 2
+#define MPEG_AUDIO_CHANNEL_MODE_MONO 3
+
+#define CRC_UNKNOWN -1
+#define CRC_PROTECTED 0
+#define CRC_NOT_PROTECTED 1
+
+#define XING_FRAMES_FLAG 0x0001
+#define XING_BYTES_FLAG 0x0002
+#define XING_TOC_FLAG 0x0004
+#define XING_VBR_SCALE_FLAG 0x0008
+
+static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS ("audio/mpeg, "
+ "mpegversion = (int) 1, "
+ "layer = (int) [ 1, 3 ], "
+ "rate = (int) [ 8000, 48000 ], channels = (int) [ 1, 2 ],"
+ "parsed=(boolean) true")
+ );
+
+static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS ("audio/mpeg, mpegversion = (int) 1, parsed=(boolean)false")
+ );
+
+static void gst_mpeg_audio_parse_finalize (GObject * object);
+
+static gboolean gst_mpeg_audio_parse_start (GstBaseParse * parse);
+static gboolean gst_mpeg_audio_parse_stop (GstBaseParse * parse);
+static gboolean gst_mpeg_audio_parse_check_valid_frame (GstBaseParse * parse,
+ GstBaseParseFrame * frame, guint * size, gint * skipsize);
+static GstFlowReturn gst_mpeg_audio_parse_parse_frame (GstBaseParse * parse,
+ GstBaseParseFrame * frame);
+static GstFlowReturn gst_mpeg_audio_parse_pre_push_frame (GstBaseParse * parse,
+ GstBaseParseFrame * frame);
+static gboolean gst_mpeg_audio_parse_convert (GstBaseParse * parse,
+ GstFormat src_format, gint64 src_value,
+ GstFormat dest_format, gint64 * dest_value);
+
+GST_BOILERPLATE (GstMpegAudioParse, gst_mpeg_audio_parse, GstBaseParse,
+ GST_TYPE_BASE_PARSE);
+
+#define GST_TYPE_MPEG_AUDIO_CHANNEL_MODE \
+ (gst_mpeg_audio_channel_mode_get_type())
+
+static const GEnumValue mpeg_audio_channel_mode[] = {
+ {MPEG_AUDIO_CHANNEL_MODE_UNKNOWN, "Unknown", "unknown"},
+ {MPEG_AUDIO_CHANNEL_MODE_MONO, "Mono", "mono"},
+ {MPEG_AUDIO_CHANNEL_MODE_DUAL_CHANNEL, "Dual Channel", "dual-channel"},
+ {MPEG_AUDIO_CHANNEL_MODE_JOINT_STEREO, "Joint Stereo", "joint-stereo"},
+ {MPEG_AUDIO_CHANNEL_MODE_STEREO, "Stereo", "stereo"},
+ {0, NULL, NULL},
+};
+
+static GType
+gst_mpeg_audio_channel_mode_get_type (void)
+{
+ static GType mpeg_audio_channel_mode_type = 0;
+
+ if (!mpeg_audio_channel_mode_type) {
+ mpeg_audio_channel_mode_type =
+ g_enum_register_static ("GstMpegAudioChannelMode",
+ mpeg_audio_channel_mode);
+ }
+ return mpeg_audio_channel_mode_type;
+}
+
+static const gchar *
+gst_mpeg_audio_channel_mode_get_nick (gint mode)
+{
+ guint i;
+ for (i = 0; i < G_N_ELEMENTS (mpeg_audio_channel_mode); i++) {
+ if (mpeg_audio_channel_mode[i].value == mode)
+ return mpeg_audio_channel_mode[i].value_nick;
+ }
+ return NULL;
+}
+
+static void
+gst_mpeg_audio_parse_base_init (gpointer klass)
+{
+ GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+
+ 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, "MPEG1 Audio Parser",
+ "Codec/Parser/Audio",
+ "Parses and frames mpeg1 audio streams (levels 1-3), provides seek",
+ "Jan Schmidt <thaytan@mad.scientist.com>,"
+ "Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>");
+}
+
+static void
+gst_mpeg_audio_parse_class_init (GstMpegAudioParseClass * klass)
+{
+ GstBaseParseClass *parse_class = GST_BASE_PARSE_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ GST_DEBUG_CATEGORY_INIT (mpeg_audio_parse_debug, "mpegaudioparse", 0,
+ "MPEG1 audio stream parser");
+
+ object_class->finalize = gst_mpeg_audio_parse_finalize;
+
+ parse_class->start = GST_DEBUG_FUNCPTR (gst_mpeg_audio_parse_start);
+ parse_class->stop = GST_DEBUG_FUNCPTR (gst_mpeg_audio_parse_stop);
+ parse_class->check_valid_frame =
+ GST_DEBUG_FUNCPTR (gst_mpeg_audio_parse_check_valid_frame);
+ parse_class->parse_frame =
+ GST_DEBUG_FUNCPTR (gst_mpeg_audio_parse_parse_frame);
+ parse_class->pre_push_frame =
+ GST_DEBUG_FUNCPTR (gst_mpeg_audio_parse_pre_push_frame);
+ parse_class->convert = GST_DEBUG_FUNCPTR (gst_mpeg_audio_parse_convert);
+
+ /* register tags */
+#define GST_TAG_CRC "has-crc"
+#define GST_TAG_MODE "channel-mode"
+
+ gst_tag_register (GST_TAG_CRC, GST_TAG_FLAG_META, G_TYPE_BOOLEAN,
+ "has crc", "Using CRC", NULL);
+ gst_tag_register (GST_TAG_MODE, GST_TAG_FLAG_ENCODED, G_TYPE_STRING,
+ "channel mode", "MPEG audio channel mode", NULL);
+
+ g_type_class_ref (GST_TYPE_MPEG_AUDIO_CHANNEL_MODE);
+}
+
+static void
+gst_mpeg_audio_parse_reset (GstMpegAudioParse * mp3parse)
+{
+ mp3parse->channels = -1;
+ mp3parse->rate = -1;
+ mp3parse->sent_codec_tag = FALSE;
+ mp3parse->last_posted_crc = CRC_UNKNOWN;
+ mp3parse->last_posted_channel_mode = MPEG_AUDIO_CHANNEL_MODE_UNKNOWN;
+
+ mp3parse->hdr_bitrate = 0;
+
+ mp3parse->xing_flags = 0;
+ mp3parse->xing_bitrate = 0;
+ mp3parse->xing_frames = 0;
+ mp3parse->xing_total_time = 0;
+ mp3parse->xing_bytes = 0;
+ mp3parse->xing_vbr_scale = 0;
+ memset (mp3parse->xing_seek_table, 0, 100);
+ memset (mp3parse->xing_seek_table_inverse, 0, 256);
+
+ mp3parse->vbri_bitrate = 0;
+ mp3parse->vbri_frames = 0;
+ mp3parse->vbri_total_time = 0;
+ mp3parse->vbri_bytes = 0;
+ mp3parse->vbri_seek_points = 0;
+ g_free (mp3parse->vbri_seek_table);
+ mp3parse->vbri_seek_table = NULL;
+
+ mp3parse->encoder_delay = 0;
+ mp3parse->encoder_padding = 0;
+}
+
+static void
+gst_mpeg_audio_parse_init (GstMpegAudioParse * mp3parse,
+ GstMpegAudioParseClass * klass)
+{
+ gst_mpeg_audio_parse_reset (mp3parse);
+}
+
+static void
+gst_mpeg_audio_parse_finalize (GObject * object)
+{
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static gboolean
+gst_mpeg_audio_parse_start (GstBaseParse * parse)
+{
+ GstMpegAudioParse *mp3parse = GST_MPEG_AUDIO_PARSE (parse);
+
+ gst_base_parse_set_min_frame_size (GST_BASE_PARSE (mp3parse), 1024);
+ GST_DEBUG_OBJECT (parse, "starting");
+
+ gst_mpeg_audio_parse_reset (mp3parse);
+
+ return TRUE;
+}
+
+static gboolean
+gst_mpeg_audio_parse_stop (GstBaseParse * parse)
+{
+ GstMpegAudioParse *mp3parse = GST_MPEG_AUDIO_PARSE (parse);
+
+ GST_DEBUG_OBJECT (parse, "stopping");
+
+ gst_mpeg_audio_parse_reset (mp3parse);
+
+ return TRUE;
+}
+
+static const guint mp3types_bitrates[2][3][16] = {
+ {
+ {0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448,},
+ {0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384,},
+ {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320,}
+ },
+ {
+ {0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256,},
+ {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160,},
+ {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160,}
+ },
+};
+
+static const guint mp3types_freqs[3][3] = { {44100, 48000, 32000},
+{22050, 24000, 16000},
+{11025, 12000, 8000}
+};
+
+static inline guint
+mp3_type_frame_length_from_header (GstMpegAudioParse * mp3parse, guint32 header,
+ guint * put_version, guint * put_layer, guint * put_channels,
+ guint * put_bitrate, guint * put_samplerate, guint * put_mode,
+ guint * put_crc)
+{
+ guint length;
+ gulong mode, samplerate, bitrate, layer, channels, padding, crc;
+ gulong version;
+ gint lsf, mpg25;
+
+ if (header & (1 << 20)) {
+ lsf = (header & (1 << 19)) ? 0 : 1;
+ mpg25 = 0;
+ } else {
+ lsf = 1;
+ mpg25 = 1;
+ }
+
+ version = 1 + lsf + mpg25;
+
+ layer = 4 - ((header >> 17) & 0x3);
+
+ crc = (header >> 16) & 0x1;
+
+ bitrate = (header >> 12) & 0xF;
+ bitrate = mp3types_bitrates[lsf][layer - 1][bitrate] * 1000;
+ /* The caller has ensured we have a valid header, so bitrate can't be
+ zero here. */
+ g_assert (bitrate != 0);
+
+ samplerate = (header >> 10) & 0x3;
+ samplerate = mp3types_freqs[lsf + mpg25][samplerate];
+
+ padding = (header >> 9) & 0x1;
+
+ mode = (header >> 6) & 0x3;
+ channels = (mode == 3) ? 1 : 2;
+
+ switch (layer) {
+ case 1:
+ length = 4 * ((bitrate * 12) / samplerate + padding);
+ break;
+ case 2:
+ length = (bitrate * 144) / samplerate + padding;
+ break;
+ default:
+ case 3:
+ length = (bitrate * 144) / (samplerate << lsf) + padding;
+ break;
+ }
+
+ GST_DEBUG_OBJECT (mp3parse, "Calculated mp3 frame length of %u bytes",
+ length);
+ GST_DEBUG_OBJECT (mp3parse, "samplerate = %lu, bitrate = %lu, version = %lu, "
+ "layer = %lu, channels = %lu, mode = %s", samplerate, bitrate, version,
+ layer, channels, gst_mpeg_audio_channel_mode_get_nick (mode));
+
+ if (put_version)
+ *put_version = version;
+ if (put_layer)
+ *put_layer = layer;
+ if (put_channels)
+ *put_channels = channels;
+ if (put_bitrate)
+ *put_bitrate = bitrate;
+ if (put_samplerate)
+ *put_samplerate = samplerate;
+ if (put_mode)
+ *put_mode = mode;
+ if (put_crc)
+ *put_crc = crc;
+
+ return length;
+}
+
+/* Minimum number of consecutive, valid-looking frames to consider
+ * for resyncing */
+#define MIN_RESYNC_FRAMES 3
+
+/* Perform extended validation to check that subsequent headers match
+ * the first header given here in important characteristics, to avoid
+ * false sync. We look for a minimum of MIN_RESYNC_FRAMES consecutive
+ * frames to match their major characteristics.
+ *
+ * If at_eos is set to TRUE, we just check that we don't find any invalid
+ * frames in whatever data is available, rather than requiring a full
+ * MIN_RESYNC_FRAMES of data.
+ *
+ * Returns TRUE if we've seen enough data to validate or reject the frame.
+ * If TRUE is returned, then *valid contains TRUE if it validated, or false
+ * if we decided it was false sync.
+ * If FALSE is returned, then *valid contains minimum needed data.
+ */
+static gboolean
+gst_mp3parse_validate_extended (GstMpegAudioParse * mp3parse, GstBuffer * buf,
+ guint32 header, int bpf, gboolean at_eos, gint * valid)
+{
+ guint32 next_header;
+ const guint8 *data;
+ guint available;
+ int frames_found = 1;
+ int offset = bpf;
+
+ available = GST_BUFFER_SIZE (buf);
+ data = GST_BUFFER_DATA (buf);
+
+ while (frames_found < MIN_RESYNC_FRAMES) {
+ /* Check if we have enough data for all these frames, plus the next
+ frame header. */
+ if (available < offset + 4) {
+ if (at_eos) {
+ /* Running out of data at EOS is fine; just accept it */
+ *valid = TRUE;
+ return TRUE;
+ } else {
+ *valid = offset + 4;
+ return FALSE;
+ }
+ }
+
+ next_header = GST_READ_UINT32_BE (data + offset);
+ GST_DEBUG_OBJECT (mp3parse, "At %d: header=%08X, header2=%08X, bpf=%d",
+ offset, (unsigned int) header, (unsigned int) next_header, bpf);
+
+/* mask the bits which are allowed to differ between frames */
+#define HDRMASK ~((0xF << 12) /* bitrate */ | \
+ (0x1 << 9) /* padding */ | \
+ (0xf << 4) /* mode|mode extension */ | \
+ (0xf)) /* copyright|emphasis */
+
+ if ((next_header & HDRMASK) != (header & HDRMASK)) {
+ /* If any of the unmasked bits don't match, then it's not valid */
+ GST_DEBUG_OBJECT (mp3parse, "next header doesn't match "
+ "(header=%08X (%08X), header2=%08X (%08X), bpf=%d)",
+ (guint) header, (guint) header & HDRMASK, (guint) next_header,
+ (guint) next_header & HDRMASK, bpf);
+ *valid = FALSE;
+ return TRUE;
+ } else if ((((next_header >> 12) & 0xf) == 0) ||
+ (((next_header >> 12) & 0xf) == 0xf)) {
+ /* The essential parts were the same, but the bitrate held an
+ invalid value - also reject */
+ GST_DEBUG_OBJECT (mp3parse, "next header invalid (bitrate)");
+ *valid = FALSE;
+ return TRUE;
+ }
+
+ bpf = mp3_type_frame_length_from_header (mp3parse, next_header,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+
+ offset += bpf;
+ frames_found++;
+ }
+
+ *valid = TRUE;
+ return TRUE;
+}
+
+static gboolean
+gst_mpeg_audio_parse_head_check (GstMpegAudioParse * mp3parse,
+ unsigned long head)
+{
+ GST_DEBUG_OBJECT (mp3parse, "checking mp3 header 0x%08lx", head);
+ /* if it's not a valid sync */
+ if ((head & 0xffe00000) != 0xffe00000) {
+ GST_WARNING_OBJECT (mp3parse, "invalid sync");
+ return FALSE;
+ }
+ /* if it's an invalid MPEG version */
+ if (((head >> 19) & 3) == 0x1) {
+ GST_WARNING_OBJECT (mp3parse, "invalid MPEG version: 0x%lx",
+ (head >> 19) & 3);
+ return FALSE;
+ }
+ /* if it's an invalid layer */
+ if (!((head >> 17) & 3)) {
+ GST_WARNING_OBJECT (mp3parse, "invalid layer: 0x%lx", (head >> 17) & 3);
+ return FALSE;
+ }
+ /* if it's an invalid bitrate */
+ if (((head >> 12) & 0xf) == 0x0) {
+ GST_WARNING_OBJECT (mp3parse, "invalid bitrate: 0x%lx."
+ "Free format files are not supported yet", (head >> 12) & 0xf);
+ return FALSE;
+ }
+ if (((head >> 12) & 0xf) == 0xf) {
+ GST_WARNING_OBJECT (mp3parse, "invalid bitrate: 0x%lx", (head >> 12) & 0xf);
+ return FALSE;
+ }
+ /* if it's an invalid samplerate */
+ if (((head >> 10) & 0x3) == 0x3) {
+ GST_WARNING_OBJECT (mp3parse, "invalid samplerate: 0x%lx",
+ (head >> 10) & 0x3);
+ return FALSE;
+ }
+
+ if ((head & 0x3) == 0x2) {
+ /* Ignore this as there are some files with emphasis 0x2 that can
+ * be played fine. See BGO #537235 */
+ GST_WARNING_OBJECT (mp3parse, "invalid emphasis: 0x%lx", head & 0x3);
+ }
+
+ return TRUE;
+}
+
+static gboolean
+gst_mpeg_audio_parse_check_valid_frame (GstBaseParse * parse,
+ GstBaseParseFrame * frame, guint * framesize, gint * skipsize)
+{
+ GstMpegAudioParse *mp3parse = GST_MPEG_AUDIO_PARSE (parse);
+ GstBuffer *buf = frame->buffer;
+ GstByteReader reader = GST_BYTE_READER_INIT_FROM_BUFFER (buf);
+ gint off, bpf;
+ gboolean lost_sync, draining, valid, caps_change;
+ guint32 header;
+ guint bitrate, layer, rate, channels, version, mode, crc;
+
+ if (G_UNLIKELY (GST_BUFFER_SIZE (buf) < 6))
+ return FALSE;
+
+ off = gst_byte_reader_masked_scan_uint32 (&reader, 0xffe00000, 0xffe00000,
+ 0, GST_BUFFER_SIZE (buf));
+
+ GST_LOG_OBJECT (parse, "possible sync at buffer offset %d", off);
+
+ /* didn't find anything that looks like a sync word, skip */
+ if (off < 0) {
+ *skipsize = GST_BUFFER_SIZE (buf) - 3;
+ return FALSE;
+ }
+
+ /* possible frame header, but not at offset 0? skip bytes before sync */
+ if (off > 0) {
+ *skipsize = off;
+ return FALSE;
+ }
+
+ /* make sure the values in the frame header look sane */
+ header = GST_READ_UINT32_BE (GST_BUFFER_DATA (buf));
+ if (!gst_mpeg_audio_parse_head_check (mp3parse, header)) {
+ *skipsize = 1;
+ return FALSE;
+ }
+
+ GST_LOG_OBJECT (parse, "got frame");
+
+ bpf = mp3_type_frame_length_from_header (mp3parse, header,
+ &version, &layer, &channels, &bitrate, &rate, &mode, &crc);
+ g_assert (bpf != 0);
+
+ if (channels != mp3parse->channels || rate != mp3parse->rate ||
+ layer != mp3parse->layer || version != mp3parse->version)
+ caps_change = TRUE;
+ else
+ caps_change = FALSE;
+
+ lost_sync = GST_BASE_PARSE_LOST_SYNC (parse);
+ draining = GST_BASE_PARSE_DRAINING (parse);
+
+ if (!draining && (lost_sync || caps_change)) {
+ if (!gst_mp3parse_validate_extended (mp3parse, buf, header, bpf, draining,
+ &valid)) {
+ /* not enough data */
+ gst_base_parse_set_min_frame_size (parse, valid);
+ *skipsize = 0;
+ return FALSE;
+ } else {
+ if (!valid) {
+ *skipsize = off + 2;
+ return FALSE;
+ }
+ }
+ } else if (draining && lost_sync && caps_change && mp3parse->rate > 0) {
+ /* avoid caps jitter that we can't be sure of */
+ *skipsize = off + 2;
+ return FALSE;
+ }
+
+ *framesize = bpf;
+ return TRUE;
+}
+
+static void
+gst_mpeg_audio_parse_handle_first_frame (GstMpegAudioParse * mp3parse,
+ GstBuffer * buf)
+{
+ const guint32 xing_id = 0x58696e67; /* 'Xing' in hex */
+ const guint32 info_id = 0x496e666f; /* 'Info' in hex - found in LAME CBR files */
+ const guint32 vbri_id = 0x56425249; /* 'VBRI' in hex */
+ const guint32 lame_id = 0x4c414d45; /* 'LAME' in hex */
+ gint offset_xing, offset_vbri;
+ guint64 avail;
+ gint64 upstream_total_bytes = 0;
+ GstFormat fmt = GST_FORMAT_BYTES;
+ guint32 read_id_xing = 0, read_id_vbri = 0;
+ const guint8 *data;
+ guint bitrate;
+
+ if (mp3parse->sent_codec_tag)
+ return;
+
+ /* Check first frame for Xing info */
+ if (mp3parse->version == 1) { /* MPEG-1 file */
+ if (mp3parse->channels == 1)
+ offset_xing = 0x11;
+ else
+ offset_xing = 0x20;
+ } else { /* MPEG-2 header */
+ if (mp3parse->channels == 1)
+ offset_xing = 0x09;
+ else
+ offset_xing = 0x11;
+ }
+
+ /* The VBRI tag is always at offset 0x20 */
+ offset_vbri = 0x20;
+
+ /* Skip the 4 bytes of the MP3 header too */
+ offset_xing += 4;
+ offset_vbri += 4;
+
+ /* Check if we have enough data to read the Xing header */
+ avail = GST_BUFFER_SIZE (buf);
+ data = GST_BUFFER_DATA (buf);
+
+ if (avail >= offset_xing + 4) {
+ read_id_xing = GST_READ_UINT32_BE (data + offset_xing);
+ }
+ if (avail >= offset_vbri + 4) {
+ read_id_vbri = GST_READ_UINT32_BE (data + offset_vbri);
+ }
+
+ /* obtain real upstream total bytes */
+ fmt = GST_FORMAT_BYTES;
+ if (!gst_pad_query_peer_duration (GST_BASE_PARSE_SINK_PAD (GST_BASE_PARSE
+ (mp3parse)), &fmt, &upstream_total_bytes))
+ upstream_total_bytes = 0;
+
+ if (read_id_xing == xing_id || read_id_xing == info_id) {
+ guint32 xing_flags;
+ guint bytes_needed = offset_xing + 8;
+ gint64 total_bytes;
+ GstClockTime total_time;
+
+ GST_DEBUG_OBJECT (mp3parse, "Found Xing header marker 0x%x", xing_id);
+
+ /* Move data after Xing header */
+ data += offset_xing + 4;
+
+ /* Read 4 base bytes of flags, big-endian */
+ xing_flags = GST_READ_UINT32_BE (data);
+ data += 4;
+ if (xing_flags & XING_FRAMES_FLAG)
+ bytes_needed += 4;
+ if (xing_flags & XING_BYTES_FLAG)
+ bytes_needed += 4;
+ if (xing_flags & XING_TOC_FLAG)
+ bytes_needed += 100;
+ if (xing_flags & XING_VBR_SCALE_FLAG)
+ bytes_needed += 4;
+ if (avail < bytes_needed) {
+ GST_DEBUG_OBJECT (mp3parse,
+ "Not enough data to read Xing header (need %d)", bytes_needed);
+ return;
+ }
+
+ GST_DEBUG_OBJECT (mp3parse, "Reading Xing header");
+ mp3parse->xing_flags = xing_flags;
+
+ if (xing_flags & XING_FRAMES_FLAG) {
+ mp3parse->xing_frames = GST_READ_UINT32_BE (data);
+ if (mp3parse->xing_frames == 0) {
+ GST_WARNING_OBJECT (mp3parse,
+ "Invalid number of frames in Xing header");
+ mp3parse->xing_flags &= ~XING_FRAMES_FLAG;
+ } else {
+ mp3parse->xing_total_time = gst_util_uint64_scale (GST_SECOND,
+ (guint64) (mp3parse->xing_frames) * (mp3parse->spf),
+ mp3parse->rate);
+ }
+
+ data += 4;
+ } else {
+ mp3parse->xing_frames = 0;
+ mp3parse->xing_total_time = 0;
+ }
+
+ if (xing_flags & XING_BYTES_FLAG) {
+ mp3parse->xing_bytes = GST_READ_UINT32_BE (data);
+ if (mp3parse->xing_bytes == 0) {
+ GST_WARNING_OBJECT (mp3parse, "Invalid number of bytes in Xing header");
+ mp3parse->xing_flags &= ~XING_BYTES_FLAG;
+ }
+ data += 4;
+ } else {
+ mp3parse->xing_bytes = 0;
+ }
+
+ /* If we know the upstream size and duration, compute the
+ * total bitrate, rounded up to the nearest kbit/sec */
+ if ((total_time = mp3parse->xing_total_time) &&
+ (total_bytes = mp3parse->xing_bytes)) {
+ mp3parse->xing_bitrate = gst_util_uint64_scale (total_bytes,
+ 8 * GST_SECOND, total_time);
+ mp3parse->xing_bitrate += 500;
+ mp3parse->xing_bitrate -= mp3parse->xing_bitrate % 1000;
+ }
+
+ if (xing_flags & XING_TOC_FLAG) {
+ int i, percent = 0;
+ guchar *table = mp3parse->xing_seek_table;
+ guchar old = 0, new;
+ guint first;
+
+ first = data[0];
+ GST_DEBUG_OBJECT (mp3parse,
+ "Subtracting initial offset of %d bytes from Xing TOC", first);
+
+ /* xing seek table: percent time -> 1/256 bytepos */
+ for (i = 0; i < 100; i++) {
+ new = data[i] - first;
+ if (old > new) {
+ GST_WARNING_OBJECT (mp3parse, "Skipping broken Xing TOC");
+ mp3parse->xing_flags &= ~XING_TOC_FLAG;
+ goto skip_toc;
+ }
+ mp3parse->xing_seek_table[i] = old = new;
+ }
+
+ /* build inverse table: 1/256 bytepos -> 1/100 percent time */
+ for (i = 0; i < 256; i++) {
+ while (percent < 99 && table[percent + 1] <= i)
+ percent++;
+
+ if (table[percent] == i) {
+ mp3parse->xing_seek_table_inverse[i] = percent * 100;
+ } else if (table[percent] < i && percent < 99) {
+ gdouble fa, fb, fx;
+ gint a = percent, b = percent + 1;
+
+ fa = table[a];
+ fb = table[b];
+ fx = (b - a) / (fb - fa) * (i - fa) + a;
+ mp3parse->xing_seek_table_inverse[i] = (guint16) (fx * 100);
+ } else if (percent == 99) {
+ gdouble fa, fb, fx;
+ gint a = percent, b = 100;
+
+ fa = table[a];
+ fb = 256.0;
+ fx = (b - a) / (fb - fa) * (i - fa) + a;
+ mp3parse->xing_seek_table_inverse[i] = (guint16) (fx * 100);
+ }
+ }
+ skip_toc:
+ data += 100;
+ } else {
+ memset (mp3parse->xing_seek_table, 0, 100);
+ memset (mp3parse->xing_seek_table_inverse, 0, 256);
+ }
+
+ if (xing_flags & XING_VBR_SCALE_FLAG) {
+ mp3parse->xing_vbr_scale = GST_READ_UINT32_BE (data);
+ data += 4;
+ } else
+ mp3parse->xing_vbr_scale = 0;
+
+ GST_DEBUG_OBJECT (mp3parse, "Xing header reported %u frames, time %"
+ GST_TIME_FORMAT ", %u bytes, vbr scale %u", mp3parse->xing_frames,
+ GST_TIME_ARGS (mp3parse->xing_total_time), mp3parse->xing_bytes,
+ mp3parse->xing_vbr_scale);
+
+ /* check for truncated file */
+ if (upstream_total_bytes && mp3parse->xing_bytes &&
+ mp3parse->xing_bytes * 0.8 > upstream_total_bytes) {
+ GST_WARNING_OBJECT (mp3parse, "File appears to have been truncated; "
+ "invalidating Xing header duration and size");
+ mp3parse->xing_flags &= ~XING_BYTES_FLAG;
+ mp3parse->xing_flags &= ~XING_FRAMES_FLAG;
+ }
+
+ /* Optional LAME tag? */
+ if (avail - bytes_needed >= 36 && GST_READ_UINT32_BE (data) == lame_id) {
+ gchar lame_version[10] = { 0, };
+ guint tag_rev;
+ guint32 encoder_delay, encoder_padding;
+
+ memcpy (lame_version, data, 9);
+ data += 9;
+ tag_rev = data[0] >> 4;
+ GST_DEBUG_OBJECT (mp3parse, "Found LAME tag revision %d created by '%s'",
+ tag_rev, lame_version);
+
+ /* Skip all the information we're not interested in */
+ data += 12;
+ /* Encoder delay and end padding */
+ encoder_delay = GST_READ_UINT24_BE (data);
+ encoder_delay >>= 12;
+ encoder_padding = GST_READ_UINT24_BE (data);
+ encoder_padding &= 0x000fff;
+
+ mp3parse->encoder_delay = encoder_delay;
+ mp3parse->encoder_padding = encoder_padding;
+
+ GST_DEBUG_OBJECT (mp3parse, "Encoder delay %u, encoder padding %u",
+ encoder_delay, encoder_padding);
+ }
+ }
+
+ if (read_id_vbri == vbri_id) {
+ gint64 total_bytes, total_frames;
+ GstClockTime total_time;
+ guint16 nseek_points;
+
+ GST_DEBUG_OBJECT (mp3parse, "Found VBRI header marker 0x%x", vbri_id);
+
+ if (avail < offset_vbri + 26) {
+ GST_DEBUG_OBJECT (mp3parse,
+ "Not enough data to read VBRI header (need %d)", offset_vbri + 26);
+ return;
+ }
+
+ GST_DEBUG_OBJECT (mp3parse, "Reading VBRI header");
+
+ /* Move data after VBRI header */
+ data += offset_vbri + 4;
+
+ if (GST_READ_UINT16_BE (data) != 0x0001) {
+ GST_WARNING_OBJECT (mp3parse,
+ "Unsupported VBRI version 0x%x", GST_READ_UINT16_BE (data));
+ return;
+ }
+ data += 2;
+
+ /* Skip encoder delay */
+ data += 2;
+
+ /* Skip quality */
+ data += 2;
+
+ total_bytes = GST_READ_UINT32_BE (data);
+ if (total_bytes != 0)
+ mp3parse->vbri_bytes = total_bytes;
+ data += 4;
+
+ total_frames = GST_READ_UINT32_BE (data);
+ if (total_frames != 0) {
+ mp3parse->vbri_frames = total_frames;
+ mp3parse->vbri_total_time = gst_util_uint64_scale (GST_SECOND,
+ (guint64) (mp3parse->vbri_frames) * (mp3parse->spf), mp3parse->rate);
+ }
+ data += 4;
+
+ /* If we know the upstream size and duration, compute the
+ * total bitrate, rounded up to the nearest kbit/sec */
+ if ((total_time = mp3parse->vbri_total_time) &&
+ (total_bytes = mp3parse->vbri_bytes)) {
+ mp3parse->vbri_bitrate = gst_util_uint64_scale (total_bytes,
+ 8 * GST_SECOND, total_time);
+ mp3parse->vbri_bitrate += 500;
+ mp3parse->vbri_bitrate -= mp3parse->vbri_bitrate % 1000;
+ }
+
+ nseek_points = GST_READ_UINT16_BE (data);
+ data += 2;
+
+ if (nseek_points > 0) {
+ guint scale, seek_bytes, seek_frames;
+ gint i;
+
+ mp3parse->vbri_seek_points = nseek_points;
+
+ scale = GST_READ_UINT16_BE (data);
+ data += 2;
+
+ seek_bytes = GST_READ_UINT16_BE (data);
+ data += 2;
+
+ seek_frames = GST_READ_UINT16_BE (data);
+
+ if (scale == 0 || seek_bytes == 0 || seek_bytes > 4 || seek_frames == 0) {
+ GST_WARNING_OBJECT (mp3parse, "Unsupported VBRI seek table");
+ goto out_vbri;
+ }
+
+ if (avail < offset_vbri + 26 + nseek_points * seek_bytes) {
+ GST_WARNING_OBJECT (mp3parse,
+ "Not enough data to read VBRI seek table (need %d)",
+ offset_vbri + 26 + nseek_points * seek_bytes);
+ goto out_vbri;
+ }
+
+ if (seek_frames * nseek_points < total_frames - seek_frames ||
+ seek_frames * nseek_points > total_frames + seek_frames) {
+ GST_WARNING_OBJECT (mp3parse,
+ "VBRI seek table doesn't cover the complete file");
+ goto out_vbri;
+ }
+
+ if (avail < offset_vbri + 26) {
+ GST_DEBUG_OBJECT (mp3parse,
+ "Not enough data to read VBRI header (need %d)",
+ offset_vbri + 26 + nseek_points * seek_bytes);
+ return;
+ }
+
+ data = GST_BUFFER_DATA (buf);
+ data += offset_vbri + 26;
+
+ /* VBRI seek table: frame/seek_frames -> byte */
+ mp3parse->vbri_seek_table = g_new (guint32, nseek_points);
+ if (seek_bytes == 4)
+ for (i = 0; i < nseek_points; i++) {
+ mp3parse->vbri_seek_table[i] = GST_READ_UINT32_BE (data) * scale;
+ data += 4;
+ } else if (seek_bytes == 3)
+ for (i = 0; i < nseek_points; i++) {
+ mp3parse->vbri_seek_table[i] = GST_READ_UINT24_BE (data) * scale;
+ data += 3;
+ } else if (seek_bytes == 2)
+ for (i = 0; i < nseek_points; i++) {
+ mp3parse->vbri_seek_table[i] = GST_READ_UINT16_BE (data) * scale;
+ data += 2;
+ } else /* seek_bytes == 1 */
+ for (i = 0; i < nseek_points; i++) {
+ mp3parse->vbri_seek_table[i] = GST_READ_UINT8 (data) * scale;
+ data += 1;
+ }
+ }
+ out_vbri:
+
+ GST_DEBUG_OBJECT (mp3parse, "VBRI header reported %u frames, time %"
+ GST_TIME_FORMAT ", bytes %u", mp3parse->vbri_frames,
+ GST_TIME_ARGS (mp3parse->vbri_total_time), mp3parse->vbri_bytes);
+
+ /* check for truncated file */
+ if (upstream_total_bytes && mp3parse->vbri_bytes &&
+ mp3parse->vbri_bytes * 0.8 > upstream_total_bytes) {
+ GST_WARNING_OBJECT (mp3parse, "File appears to have been truncated; "
+ "invalidating VBRI header duration and size");
+ mp3parse->vbri_valid = FALSE;
+ } else {
+ mp3parse->vbri_valid = TRUE;
+ }
+ } else {
+ GST_DEBUG_OBJECT (mp3parse,
+ "Xing, LAME or VBRI header not found in first frame");
+ }
+
+ /* set duration if tables provided a valid one */
+ if (mp3parse->xing_flags & XING_FRAMES_FLAG) {
+ gst_base_parse_set_duration (GST_BASE_PARSE (mp3parse), GST_FORMAT_TIME,
+ mp3parse->xing_total_time, 0);
+ }
+ if (mp3parse->vbri_total_time != 0 && mp3parse->vbri_valid) {
+ gst_base_parse_set_duration (GST_BASE_PARSE (mp3parse), GST_FORMAT_TIME,
+ mp3parse->vbri_total_time, 0);
+ }
+
+ /* tell baseclass how nicely we can seek, and a bitrate if one found */
+ /* FIXME: fill index with seek table */
+#if 0
+ seekable = GST_BASE_PARSE_SEEK_DEFAULT;
+ if ((mp3parse->xing_flags & XING_TOC_FLAG) && mp3parse->xing_bytes &&
+ mp3parse->xing_total_time)
+ seekable = GST_BASE_PARSE_SEEK_TABLE;
+
+ if (mp3parse->vbri_seek_table && mp3parse->vbri_bytes &&
+ mp3parse->vbri_total_time)
+ seekable = GST_BASE_PARSE_SEEK_TABLE;
+#endif
+
+ if (mp3parse->xing_bitrate)
+ bitrate = mp3parse->xing_bitrate;
+ else if (mp3parse->vbri_bitrate)
+ bitrate = mp3parse->vbri_bitrate;
+ else
+ bitrate = 0;
+
+ gst_base_parse_set_average_bitrate (GST_BASE_PARSE (mp3parse), bitrate);
+}
+
+static GstFlowReturn
+gst_mpeg_audio_parse_parse_frame (GstBaseParse * parse,
+ GstBaseParseFrame * frame)
+{
+ GstMpegAudioParse *mp3parse = GST_MPEG_AUDIO_PARSE (parse);
+ GstBuffer *buf = frame->buffer;
+ guint bitrate, layer, rate, channels, version, mode, crc;
+
+ g_return_val_if_fail (GST_BUFFER_SIZE (buf) >= 4, GST_FLOW_ERROR);
+
+ if (!mp3_type_frame_length_from_header (mp3parse,
+ GST_READ_UINT32_BE (GST_BUFFER_DATA (buf)),
+ &version, &layer, &channels, &bitrate, &rate, &mode, &crc))
+ goto broken_header;
+
+ if (G_UNLIKELY (channels != mp3parse->channels || rate != mp3parse->rate ||
+ layer != mp3parse->layer || version != mp3parse->version)) {
+ GstCaps *caps = gst_caps_new_simple ("audio/mpeg",
+ "mpegversion", G_TYPE_INT, 1,
+ "mpegaudioversion", G_TYPE_INT, version,
+ "layer", G_TYPE_INT, layer,
+ "rate", G_TYPE_INT, rate,
+ "channels", G_TYPE_INT, channels, "parsed", G_TYPE_BOOLEAN, TRUE, NULL);
+ gst_buffer_set_caps (buf, caps);
+ gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (parse), caps);
+ gst_caps_unref (caps);
+
+ mp3parse->rate = rate;
+ mp3parse->channels = channels;
+ mp3parse->layer = layer;
+ mp3parse->version = version;
+
+ /* see http://www.codeproject.com/audio/MPEGAudioInfo.asp */
+ if (mp3parse->layer == 1)
+ mp3parse->spf = 384;
+ else if (mp3parse->layer == 2)
+ mp3parse->spf = 1152;
+ else if (mp3parse->version == 1) {
+ mp3parse->spf = 1152;
+ } else {
+ /* MPEG-2 or "2.5" */
+ mp3parse->spf = 576;
+ }
+
+ /* lead_in:
+ * We start pushing 9 frames earlier (29 frames for MPEG2) than
+ * segment start to be able to decode the first frame we want.
+ * 9 (29) frames are the theoretical maximum of frames that contain
+ * data for the current frame (bit reservoir).
+ *
+ * lead_out:
+ * Some mp3 streams have an offset in the timestamps, for which we have to
+ * push the frame *after* the end position in order for the decoder to be
+ * able to decode everything up until the segment.stop position. */
+ gst_base_parse_set_frame_rate (parse, mp3parse->rate, mp3parse->spf,
+ (version == 1) ? 10 : 30, 2);
+ }
+
+ mp3parse->hdr_bitrate = bitrate;
+
+ /* For first frame; check for seek tables and output a codec tag */
+ gst_mpeg_audio_parse_handle_first_frame (mp3parse, buf);
+
+ /* store some frame info for later processing */
+ mp3parse->last_crc = crc;
+ mp3parse->last_mode = mode;
+
+ return GST_FLOW_OK;
+
+/* ERRORS */
+broken_header:
+ {
+ /* this really shouldn't ever happen */
+ GST_ELEMENT_ERROR (parse, STREAM, DECODE, (NULL), (NULL));
+ return GST_FLOW_ERROR;
+ }
+}
+
+static gboolean
+gst_mpeg_audio_parse_time_to_bytepos (GstMpegAudioParse * mp3parse,
+ GstClockTime ts, gint64 * bytepos)
+{
+ gint64 total_bytes;
+ GstClockTime total_time;
+
+ /* If XING seek table exists use this for time->byte conversion */
+ if ((mp3parse->xing_flags & XING_TOC_FLAG) &&
+ (total_bytes = mp3parse->xing_bytes) &&
+ (total_time = mp3parse->xing_total_time)) {
+ gdouble fa, fb, fx;
+ gdouble percent =
+ CLAMP ((100.0 * gst_util_guint64_to_gdouble (ts)) /
+ gst_util_guint64_to_gdouble (total_time), 0.0, 100.0);
+ gint index = CLAMP (percent, 0, 99);
+
+ fa = mp3parse->xing_seek_table[index];
+ if (index < 99)
+ fb = mp3parse->xing_seek_table[index + 1];
+ else
+ fb = 256.0;
+
+ fx = fa + (fb - fa) * (percent - index);
+
+ *bytepos = (1.0 / 256.0) * fx * total_bytes;
+
+ return TRUE;
+ }
+
+ if (mp3parse->vbri_seek_table && (total_bytes = mp3parse->vbri_bytes) &&
+ (total_time = mp3parse->vbri_total_time)) {
+ gint i, j;
+ gdouble a, b, fa, fb;
+
+ i = gst_util_uint64_scale (ts, mp3parse->vbri_seek_points - 1, total_time);
+ i = CLAMP (i, 0, mp3parse->vbri_seek_points - 1);
+
+ a = gst_guint64_to_gdouble (gst_util_uint64_scale (i, total_time,
+ mp3parse->vbri_seek_points));
+ fa = 0.0;
+ for (j = i; j >= 0; j--)
+ fa += mp3parse->vbri_seek_table[j];
+
+ if (i + 1 < mp3parse->vbri_seek_points) {
+ b = gst_guint64_to_gdouble (gst_util_uint64_scale (i + 1, total_time,
+ mp3parse->vbri_seek_points));
+ fb = fa + mp3parse->vbri_seek_table[i + 1];
+ } else {
+ b = gst_guint64_to_gdouble (total_time);
+ fb = total_bytes;
+ }
+
+ *bytepos = fa + ((fb - fa) / (b - a)) * (gst_guint64_to_gdouble (ts) - a);
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gboolean
+gst_mpeg_audio_parse_bytepos_to_time (GstMpegAudioParse * mp3parse,
+ gint64 bytepos, GstClockTime * ts)
+{
+ gint64 total_bytes;
+ GstClockTime total_time;
+
+ /* If XING seek table exists use this for byte->time conversion */
+ if ((mp3parse->xing_flags & XING_TOC_FLAG) &&
+ (total_bytes = mp3parse->xing_bytes) &&
+ (total_time = mp3parse->xing_total_time)) {
+ gdouble fa, fb, fx;
+ gdouble pos;
+ gint index;
+
+ pos = CLAMP ((bytepos * 256.0) / total_bytes, 0.0, 256.0);
+ index = CLAMP (pos, 0, 255);
+ fa = mp3parse->xing_seek_table_inverse[index];
+ if (index < 255)
+ fb = mp3parse->xing_seek_table_inverse[index + 1];
+ else
+ fb = 10000.0;
+
+ fx = fa + (fb - fa) * (pos - index);
+
+ *ts = (1.0 / 10000.0) * fx * gst_util_guint64_to_gdouble (total_time);
+
+ return TRUE;
+ }
+
+ if (mp3parse->vbri_seek_table &&
+ (total_bytes = mp3parse->vbri_bytes) &&
+ (total_time = mp3parse->vbri_total_time)) {
+ gint i = 0;
+ guint64 sum = 0;
+ gdouble a, b, fa, fb;
+
+ do {
+ sum += mp3parse->vbri_seek_table[i];
+ i++;
+ } while (i + 1 < mp3parse->vbri_seek_points
+ && sum + mp3parse->vbri_seek_table[i] < bytepos);
+ i--;
+
+ a = gst_guint64_to_gdouble (sum);
+ fa = gst_guint64_to_gdouble (gst_util_uint64_scale (i, total_time,
+ mp3parse->vbri_seek_points));
+
+ if (i + 1 < mp3parse->vbri_seek_points) {
+ b = a + mp3parse->vbri_seek_table[i + 1];
+ fb = gst_guint64_to_gdouble (gst_util_uint64_scale (i + 1, total_time,
+ mp3parse->vbri_seek_points));
+ } else {
+ b = total_bytes;
+ fb = gst_guint64_to_gdouble (total_time);
+ }
+
+ *ts = gst_gdouble_to_guint64 (fa + ((fb - fa) / (b - a)) * (bytepos - a));
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gboolean
+gst_mpeg_audio_parse_convert (GstBaseParse * parse, GstFormat src_format,
+ gint64 src_value, GstFormat dest_format, gint64 * dest_value)
+{
+ GstMpegAudioParse *mp3parse = GST_MPEG_AUDIO_PARSE (parse);
+ gboolean res = FALSE;
+
+ if (src_format == GST_FORMAT_TIME && dest_format == GST_FORMAT_BYTES)
+ res =
+ gst_mpeg_audio_parse_time_to_bytepos (mp3parse, src_value, dest_value);
+ else if (src_format == GST_FORMAT_BYTES && dest_format == GST_FORMAT_TIME)
+ res = gst_mpeg_audio_parse_bytepos_to_time (mp3parse, src_value,
+ (GstClockTime *) dest_value);
+
+ /* if no tables, fall back to default estimated rate based conversion */
+ if (!res)
+ return gst_base_parse_convert_default (parse, src_format, src_value,
+ dest_format, dest_value);
+
+ return res;
+}
+
+static GstFlowReturn
+gst_mpeg_audio_parse_pre_push_frame (GstBaseParse * parse,
+ GstBaseParseFrame * frame)
+{
+ GstMpegAudioParse *mp3parse = GST_MPEG_AUDIO_PARSE (parse);
+ GstTagList *taglist;
+
+ /* tag sending done late enough in hook to ensure pending events
+ * have already been sent */
+
+ if (!mp3parse->sent_codec_tag) {
+ gchar *codec;
+
+ /* codec tag */
+ if (mp3parse->layer == 3) {
+ codec = g_strdup_printf ("MPEG %d Audio, Layer %d (MP3)",
+ mp3parse->version, mp3parse->layer);
+ } else {
+ codec = g_strdup_printf ("MPEG %d Audio, Layer %d",
+ mp3parse->version, mp3parse->layer);
+ }
+ taglist = gst_tag_list_new ();
+ gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
+ GST_TAG_AUDIO_CODEC, codec, NULL);
+ if (mp3parse->hdr_bitrate > 0 && mp3parse->xing_bitrate == 0 &&
+ mp3parse->vbri_bitrate == 0) {
+ /* We don't have a VBR bitrate, so post the available bitrate as
+ * nominal and let baseparse calculate the real bitrate */
+ gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
+ GST_TAG_NOMINAL_BITRATE, mp3parse->hdr_bitrate, NULL);
+ }
+ gst_element_found_tags_for_pad (GST_ELEMENT (mp3parse),
+ GST_BASE_PARSE_SRC_PAD (mp3parse), taglist);
+ g_free (codec);
+
+ /* also signals the end of first-frame processing */
+ mp3parse->sent_codec_tag = TRUE;
+ }
+
+ /* we will create a taglist (if any of the parameters has changed)
+ * to add the tags that changed */
+ taglist = NULL;
+ if (mp3parse->last_posted_crc != mp3parse->last_crc) {
+ gboolean using_crc;
+
+ if (!taglist) {
+ taglist = gst_tag_list_new ();
+ }
+ mp3parse->last_posted_crc = mp3parse->last_crc;
+ if (mp3parse->last_posted_crc == CRC_PROTECTED) {
+ using_crc = TRUE;
+ } else {
+ using_crc = FALSE;
+ }
+ gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, GST_TAG_CRC,
+ using_crc, NULL);
+ }
+
+ if (mp3parse->last_posted_channel_mode != mp3parse->last_mode) {
+ if (!taglist) {
+ taglist = gst_tag_list_new ();
+ }
+ mp3parse->last_posted_channel_mode = mp3parse->last_mode;
+
+ gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, GST_TAG_MODE,
+ gst_mpeg_audio_channel_mode_get_nick (mp3parse->last_mode), NULL);
+ }
+
+ /* if the taglist exists, we need to send it */
+ if (taglist) {
+ gst_element_found_tags_for_pad (GST_ELEMENT (mp3parse),
+ GST_BASE_PARSE_SRC_PAD (mp3parse), taglist);
+ }
+
+ /* usual clipping applies */
+ frame->flags |= GST_BASE_PARSE_FRAME_FLAG_CLIP;
+
+ return GST_FLOW_OK;
+}
diff --git a/gst/audioparsers/gstmpegaudioparse.h b/gst/audioparsers/gstmpegaudioparse.h
new file mode 100644
index 000000000..758000130
--- /dev/null
+++ b/gst/audioparsers/gstmpegaudioparse.h
@@ -0,0 +1,111 @@
+/* GStreamer MPEG audio parser
+ * Copyright (C) 2006-2007 Jan Schmidt <thaytan@mad.scientist.com>
+ * Copyright (C) 2010 Mark Nauwelaerts <mnauw users sf net>
+ * Copyright (C) 2010 Nokia Corporation. All rights reserved.
+ * Contact: Stefan Kost <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_MPEG_AUDIO_PARSE_H__
+#define __GST_MPEG_AUDIO_PARSE_H__
+
+#include <gst/gst.h>
+#include <gst/base/gstbaseparse.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_MPEG_AUDIO_PARSE \
+ (gst_mpeg_audio_parse_get_type())
+#define GST_MPEG_AUDIO_PARSE(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_MPEG_AUDIO_PARSE, GstMpegAudioParse))
+#define GST_MPEG_AUDIO_PARSE_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_MPEG_AUDIO_PARSE, GstMpegAudioParseClass))
+#define GST_IS_MPEG_AUDIO_PARSE(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_MPEG_AUDIO_PARSE))
+#define GST_IS_MPEG_AUDIO_PARSE_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_MPEG_AUDIO_PARSE))
+
+typedef struct _GstMpegAudioParse GstMpegAudioParse;
+typedef struct _GstMpegAudioParseClass GstMpegAudioParseClass;
+
+/**
+ * GstMpegAudioParse:
+ *
+ * The opaque GstMpegAudioParse object
+ */
+struct _GstMpegAudioParse {
+ GstBaseParse baseparse;
+
+ /*< private >*/
+ gint rate;
+ gint channels;
+ gint layer;
+ gint version;
+
+ GstClockTime max_bitreservoir;
+ /* samples per frame */
+ gint spf;
+
+ gboolean sent_codec_tag;
+ guint last_posted_bitrate;
+ gint last_posted_crc, last_crc;
+ guint last_posted_channel_mode, last_mode;
+
+ /* Bitrate from non-vbr headers */
+ guint32 hdr_bitrate;
+
+ /* Xing info */
+ guint32 xing_flags;
+ guint32 xing_frames;
+ GstClockTime xing_total_time;
+ guint32 xing_bytes;
+ /* percent -> filepos mapping */
+ guchar xing_seek_table[100];
+ /* filepos -> percent mapping */
+ guint16 xing_seek_table_inverse[256];
+ guint32 xing_vbr_scale;
+ guint xing_bitrate;
+
+ /* VBRI info */
+ guint32 vbri_frames;
+ GstClockTime vbri_total_time;
+ guint32 vbri_bytes;
+ guint vbri_bitrate;
+ guint vbri_seek_points;
+ guint32 *vbri_seek_table;
+ gboolean vbri_valid;
+
+ /* LAME info */
+ guint32 encoder_delay;
+ guint32 encoder_padding;
+};
+
+/**
+ * GstMpegAudioParseClass:
+ * @parent_class: Element parent class.
+ *
+ * The opaque GstMpegAudioParseClass data structure.
+ */
+struct _GstMpegAudioParseClass {
+ GstBaseParseClass baseparse_class;
+};
+
+GType gst_mpeg_audio_parse_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_MPEG_AUDIO_PARSE_H__ */
diff --git a/gst/audioparsers/plugin.c b/gst/audioparsers/plugin.c
new file mode 100644
index 000000000..ae8332d3f
--- /dev/null
+++ b/gst/audioparsers/plugin.c
@@ -0,0 +1,57 @@
+/* GStreamer audio parsers
+ * Copyright (C) 2009 Tim-Philipp Müller <tim centricular net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "gstaacparse.h"
+#include "gstamrparse.h"
+#include "gstac3parse.h"
+#include "gstdcaparse.h"
+#include "gstflacparse.h"
+#include "gstmpegaudioparse.h"
+
+static gboolean
+plugin_init (GstPlugin * plugin)
+{
+ gboolean ret;
+
+ ret = gst_element_register (plugin, "aacparse",
+ GST_RANK_PRIMARY + 1, GST_TYPE_AAC_PARSE);
+ ret &= gst_element_register (plugin, "amrparse",
+ GST_RANK_PRIMARY + 1, GST_TYPE_AMR_PARSE);
+ ret &= gst_element_register (plugin, "ac3parse",
+ GST_RANK_PRIMARY + 1, GST_TYPE_AC3_PARSE);
+ ret &= gst_element_register (plugin, "dcaparse",
+ GST_RANK_PRIMARY + 1, GST_TYPE_DCA_PARSE);
+ ret &= gst_element_register (plugin, "flacparse",
+ GST_RANK_PRIMARY + 1, GST_TYPE_FLAC_PARSE);
+ ret &= gst_element_register (plugin, "mpegaudioparse",
+ GST_RANK_PRIMARY + 2, GST_TYPE_MPEG_AUDIO_PARSE);
+
+ return ret;
+}
+
+
+GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
+ GST_VERSION_MINOR,
+ "audioparsers",
+ "Parsers for various audio formats",
+ plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN);
diff --git a/gst/auparse/Makefile.am b/gst/auparse/Makefile.am
index 08b319346..a79fb7b5b 100644
--- a/gst/auparse/Makefile.am
+++ b/gst/auparse/Makefile.am
@@ -7,3 +7,17 @@ libgstauparse_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
libgstauparse_la_LIBTOOLFLAGS = --tag=disable-static
noinst_HEADERS = gstauparse.h
+
+Android.mk: Makefile.am $(BUILT_SOURCES)
+ androgenizer \
+ -:PROJECT libgstauparse -:SHARED libgstauparse \
+ -:TAGS eng debug \
+ -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
+ -:SOURCES $(libgstauparse_la_SOURCES) \
+ -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstauparse_la_CFLAGS) \
+ -:LDFLAGS $(libgstauparse_la_LDFLAGS) \
+ $(libgstauparse_la_LIBADD) \
+ -ldl \
+ -:PASSTHROUGH LOCAL_ARM_MODE:=arm \
+ LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \
+ > $@
diff --git a/gst/autodetect/Makefile.am b/gst/autodetect/Makefile.am
index aedd3d64c..5bf57c7d9 100644
--- a/gst/autodetect/Makefile.am
+++ b/gst/autodetect/Makefile.am
@@ -17,3 +17,17 @@ noinst_HEADERS = \
gstautodetect.h \
gstautovideosink.h \
gstautovideosrc.h
+
+Android.mk: Makefile.am $(BUILT_SOURCES)
+ androgenizer \
+ -:PROJECT libgstautodetect -:SHARED libgstautodetect \
+ -:TAGS eng debug \
+ -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
+ -:SOURCES $(libgstautodetect_la_SOURCES) \
+ -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstautodetect_la_CFLAGS) \
+ -:LDFLAGS $(libgstautodetect_la_LDFLAGS) \
+ $(libgstautodetect_la_LIBADD) \
+ -ldl \
+ -:PASSTHROUGH LOCAL_ARM_MODE:=arm \
+ LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \
+ > $@
diff --git a/gst/avi/Makefile.am b/gst/avi/Makefile.am
index 37742097f..90ea0ed49 100644
--- a/gst/avi/Makefile.am
+++ b/gst/avi/Makefile.am
@@ -25,3 +25,17 @@ libgstavi_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
libgstavi_la_LIBTOOLFLAGS = --tag=disable-static
EXTRA_DIST = README
+
+Android.mk: Makefile.am $(BUILT_SOURCES)
+ androgenizer \
+ -:PROJECT libgstavi -:SHARED libgstavi \
+ -:TAGS eng debug \
+ -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
+ -:SOURCES $(libgstavi_la_SOURCES) \
+ -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstavi_la_CFLAGS) \
+ -:LDFLAGS $(libgstavi_la_LDFLAGS) \
+ $(libgstavi_la_LIBADD) \
+ -ldl \
+ -:PASSTHROUGH LOCAL_ARM_MODE:=arm \
+ LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \
+ > $@
diff --git a/gst/avi/gstavidemux.c b/gst/avi/gstavidemux.c
index 60ac62c50..64767648d 100644
--- a/gst/avi/gstavidemux.c
+++ b/gst/avi/gstavidemux.c
@@ -2267,7 +2267,7 @@ gst_avi_demux_parse_stream (GstAviDemux * avi, GstBuffer * buf)
break;
}
default:
- g_assert_not_reached ();
+ g_return_val_if_reached (FALSE);
}
/* no caps means no stream */
@@ -2578,7 +2578,6 @@ gst_avi_demux_stream_for_id (GstAviDemux * avi, guint32 id)
static gboolean
gst_avi_demux_parse_index (GstAviDemux * avi, GstBuffer * buf)
{
- guint64 pos_before;
guint8 *data;
gsize size;
guint i, num, n;
@@ -2603,7 +2602,6 @@ gst_avi_demux_parse_index (GstAviDemux * avi, GstBuffer * buf)
GST_INFO_OBJECT (avi, "Parsing index, nr_entries = %6d", num);
index = (gst_riff_index_entry *) data;
- pos_before = avi->offset;
/* figure out if the index is 0 based or relative to the MOVI start */
entry.offset = GST_READ_UINT32_LE (&index[0].offset);
diff --git a/gst/cutter/Makefile.am b/gst/cutter/Makefile.am
index 7a2a01ce8..7524a0e2e 100644
--- a/gst/cutter/Makefile.am
+++ b/gst/cutter/Makefile.am
@@ -9,3 +9,17 @@ libgstcutter_la_LIBTOOLFLAGS = --tag=disable-static
noinst_HEADERS = gstcutter.h filter.func
EXTRA_DIST = README
+
+Android.mk: Makefile.am $(BUILT_SOURCES)
+ androgenizer \
+ -:PROJECT libgstcutter -:SHARED libgstcutter \
+ -:TAGS eng debug \
+ -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
+ -:SOURCES $(libgstcutter_la_SOURCES) \
+ -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstcutter_la_CFLAGS) \
+ -:LDFLAGS $(libgstcutter_la_LDFLAGS) \
+ $(libgstcutter_la_LIBADD) \
+ -ldl \
+ -:PASSTHROUGH LOCAL_ARM_MODE:=arm \
+ LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \
+ > $@
diff --git a/gst/debugutils/Makefile.am b/gst/debugutils/Makefile.am
index d905413c1..7f3edf0ad 100644
--- a/gst/debugutils/Makefile.am
+++ b/gst/debugutils/Makefile.am
@@ -51,3 +51,16 @@ libgstdebug_la_LIBADD = $(GST_LIBS) $(GST_BASE_LIBS)
libgstdebug_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
libgstdebug_la_LIBTOOLFLAGS = --tag=disable-static
+Android.mk: Makefile.am $(BUILT_SOURCES)
+ androgenizer \
+ -:PROJECT libgstdebug -:SHARED libgstdebug \
+ -:TAGS eng debug \
+ -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
+ -:SOURCES $(libgstdebug_la_SOURCES) \
+ -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstdebug_la_CFLAGS) \
+ -:LDFLAGS $(libgstdebug_la_LDFLAGS) \
+ $(libgstdebug_la_LIBADD) \
+ -ldl \
+ -:PASSTHROUGH LOCAL_ARM_MODE:=arm \
+ LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \
+ > $@
diff --git a/gst/debugutils/gstcapsdebug.c b/gst/debugutils/gstcapsdebug.c
index 3806bae6a..dcb09962d 100644
--- a/gst/debugutils/gstcapsdebug.c
+++ b/gst/debugutils/gstcapsdebug.c
@@ -32,10 +32,6 @@ GST_DEBUG_CATEGORY_STATIC (gst_caps_debug_debug);
/* prototypes */
-static void gst_caps_debug_set_property (GObject * object,
- guint property_id, const GValue * value, GParamSpec * pspec);
-static void gst_caps_debug_get_property (GObject * object,
- guint property_id, GValue * value, GParamSpec * pspec);
static void gst_caps_debug_dispose (GObject * object);
static void gst_caps_debug_finalize (GObject * object);
@@ -49,11 +45,6 @@ static GstFlowReturn gst_caps_debug_bufferalloc (GstPad * pad,
static GstStateChangeReturn
gst_caps_debug_change_state (GstElement * element, GstStateChange transition);
-enum
-{
- PROP_0
-};
-
/* pad templates */
static GstStaticPadTemplate gst_caps_debug_sink_template =
@@ -97,8 +88,6 @@ gst_caps_debug_class_init (GstCapsDebugClass * klass)
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
- gobject_class->set_property = gst_caps_debug_set_property;
- gobject_class->get_property = gst_caps_debug_get_property;
gobject_class->dispose = gst_caps_debug_dispose;
gobject_class->finalize = gst_caps_debug_finalize;
element_class->change_state = GST_DEBUG_FUNCPTR (gst_caps_debug_change_state);
@@ -133,45 +122,8 @@ gst_caps_debug_init (GstCapsDebug * capsdebug,
}
void
-gst_caps_debug_set_property (GObject * object, guint property_id,
- const GValue * value, GParamSpec * pspec)
-{
- GstCapsDebug *capsdebug;
-
- g_return_if_fail (GST_IS_CAPS_DEBUG (object));
- capsdebug = GST_CAPS_DEBUG (object);
-
- switch (property_id) {
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-void
-gst_caps_debug_get_property (GObject * object, guint property_id,
- GValue * value, GParamSpec * pspec)
-{
- GstCapsDebug *capsdebug;
-
- g_return_if_fail (GST_IS_CAPS_DEBUG (object));
- capsdebug = GST_CAPS_DEBUG (object);
-
- switch (property_id) {
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-void
gst_caps_debug_dispose (GObject * object)
{
- GstCapsDebug *capsdebug;
-
- g_return_if_fail (GST_IS_CAPS_DEBUG (object));
- capsdebug = GST_CAPS_DEBUG (object);
-
/* clean up as possible. may be called multiple times */
G_OBJECT_CLASS (parent_class)->dispose (object);
@@ -180,11 +132,6 @@ gst_caps_debug_dispose (GObject * object)
void
gst_caps_debug_finalize (GObject * object)
{
- GstCapsDebug *capsdebug;
-
- g_return_if_fail (GST_IS_CAPS_DEBUG (object));
- capsdebug = GST_CAPS_DEBUG (object);
-
/* clean up object here */
G_OBJECT_CLASS (parent_class)->finalize (object);
@@ -199,7 +146,7 @@ gst_caps_debug_change_state (GstElement * element, GstStateChange transition)
ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
- return GST_STATE_CHANGE_SUCCESS;
+ return ret;
}
diff --git a/gst/deinterlace/Makefile.am b/gst/deinterlace/Makefile.am
index 826644a11..fcadae9d2 100644
--- a/gst/deinterlace/Makefile.am
+++ b/gst/deinterlace/Makefile.am
@@ -52,3 +52,17 @@ noinst_HEADERS = \
tvtime/tomsmocomp/tomsmocompmacros.h \
tvtime/tomsmocomp/WierdBob.inc
+Android.mk: Makefile.am $(BUILT_SOURCES)
+ androgenizer \
+ -:PROJECT libgstdeinterlace -:SHARED libgstdeinterlace \
+ -:TAGS eng debug \
+ -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
+ -:SOURCES $(libgstdeinterlace_la_SOURCES) \
+ $(nodist_libgstdeinterlace_la_SOURCES) \
+ -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstdeinterlace_la_CFLAGS) \
+ -:LDFLAGS $(libgstdeinterlace_la_LDFLAGS) \
+ $(libgstdeinterlace_la_LIBADD) \
+ -ldl \
+ -:PASSTHROUGH LOCAL_ARM_MODE:=arm \
+ LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \
+ > $@
diff --git a/gst/deinterlace/tvtime-dist.c b/gst/deinterlace/tvtime-dist.c
index 957f3beaa..e1f7ed307 100644
--- a/gst/deinterlace/tvtime-dist.c
+++ b/gst/deinterlace/tvtime-dist.c
@@ -4,9 +4,6 @@
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
-#ifndef DISABLE_ORC
-#include <orc/orc.h>
-#endif
#include <glib.h>
#ifndef _ORC_INTEGER_TYPEDEFS_
@@ -32,6 +29,7 @@ typedef unsigned __int16 orc_uint16;
typedef unsigned __int32 orc_uint32;
typedef unsigned __int64 orc_uint64;
#define ORC_UINT64_C(x) (x##Ui64)
+#define inline __inline
#else
#include <limits.h>
typedef signed char orc_int8;
@@ -71,16 +69,32 @@ typedef union
orc_int16 x4[4];
} orc_union64;
#endif
+#ifndef ORC_RESTRICT
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+#define ORC_RESTRICT restrict
+#elif defined(__GNUC__) && __GNUC__ >= 4
+#define ORC_RESTRICT __restrict__
+#else
+#define ORC_RESTRICT
+#endif
+#endif
-void deinterlace_line_vfir (guint8 * d1, const guint8 * s1, const guint8 * s2,
- const guint8 * s3, const guint8 * s4, const guint8 * s5, int n);
-void deinterlace_line_linear (guint8 * d1, const guint8 * s1, const guint8 * s2,
- int n);
-void deinterlace_line_linear_blend (guint8 * d1, const guint8 * s1,
- const guint8 * s2, const guint8 * s3, int n);
-void deinterlace_line_greedy (orc_uint8 * d1, const orc_uint8 * s1,
- const orc_uint8 * s2, const orc_uint8 * s3, const orc_uint8 * s4, int p1,
- int n);
+#ifndef DISABLE_ORC
+#include <orc/orc.h>
+#endif
+void deinterlace_line_vfir (guint8 * ORC_RESTRICT d1,
+ const guint8 * ORC_RESTRICT s1, const guint8 * ORC_RESTRICT s2,
+ const guint8 * ORC_RESTRICT s3, const guint8 * ORC_RESTRICT s4,
+ const guint8 * ORC_RESTRICT s5, int n);
+void deinterlace_line_linear (guint8 * ORC_RESTRICT d1,
+ const guint8 * ORC_RESTRICT s1, const guint8 * ORC_RESTRICT s2, int n);
+void deinterlace_line_linear_blend (guint8 * ORC_RESTRICT d1,
+ const guint8 * ORC_RESTRICT s1, const guint8 * ORC_RESTRICT s2,
+ const guint8 * ORC_RESTRICT s3, int n);
+void deinterlace_line_greedy (orc_uint8 * ORC_RESTRICT d1,
+ const orc_uint8 * ORC_RESTRICT s1, const orc_uint8 * ORC_RESTRICT s2,
+ const orc_uint8 * ORC_RESTRICT s3, const orc_uint8 * ORC_RESTRICT s4,
+ int p1, int n);
/* begin Orc C target preamble */
@@ -114,6 +128,7 @@ void deinterlace_line_greedy (orc_uint8 * d1, const orc_uint8 * s1,
#define ORC_ISNAN(x) ((((x)&0x7f800000) == 0x7f800000) && (((x)&0x007fffff) != 0))
#define ORC_DENORMAL_DOUBLE(x) ((x) & ((((x)&ORC_UINT64_C(0x7ff0000000000000)) == 0) ? ORC_UINT64_C(0xfff0000000000000) : ORC_UINT64_C(0xffffffffffffffff)))
#define ORC_ISNAN_DOUBLE(x) ((((x)&ORC_UINT64_C(0x7ff0000000000000)) == ORC_UINT64_C(0x7ff0000000000000)) && (((x)&ORC_UINT64_C(0x000fffffffffffff)) != 0))
+#ifndef ORC_RESTRICT
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
#define ORC_RESTRICT restrict
#elif defined(__GNUC__) && __GNUC__ >= 4
@@ -121,6 +136,7 @@ void deinterlace_line_greedy (orc_uint8 * d1, const orc_uint8 * s1,
#else
#define ORC_RESTRICT
#endif
+#endif
/* end Orc C target preamble */
@@ -128,8 +144,9 @@ void deinterlace_line_greedy (orc_uint8 * d1, const orc_uint8 * s1,
/* deinterlace_line_vfir */
#ifdef DISABLE_ORC
void
-deinterlace_line_vfir (guint8 * d1, const guint8 * s1, const guint8 * s2,
- const guint8 * s3, const guint8 * s4, const guint8 * s5, int n)
+deinterlace_line_vfir (guint8 * ORC_RESTRICT d1, const guint8 * ORC_RESTRICT s1,
+ const guint8 * ORC_RESTRICT s2, const guint8 * ORC_RESTRICT s3,
+ const guint8 * ORC_RESTRICT s4, const guint8 * ORC_RESTRICT s5, int n)
{
int i;
orc_int8 *ORC_RESTRICT ptr0;
@@ -167,7 +184,7 @@ deinterlace_line_vfir (guint8 * d1, const guint8 * s1, const guint8 * s2,
ptr8 = (orc_int8 *) s5;
/* 16: loadpw */
- var40.i = 0x00000004; /* 4 or 1.97626e-323f */
+ var40.i = (int) 0x00000004; /* 4 or 1.97626e-323f */
for (i = 0; i < n; i++) {
/* 0: loadb */
@@ -255,7 +272,7 @@ _backup_deinterlace_line_vfir (OrcExecutor * ORC_RESTRICT ex)
ptr8 = (orc_int8 *) ex->arrays[8];
/* 16: loadpw */
- var40.i = 0x00000004; /* 4 or 1.97626e-323f */
+ var40.i = (int) 0x00000004; /* 4 or 1.97626e-323f */
for (i = 0; i < n; i++) {
/* 0: loadb */
@@ -303,8 +320,9 @@ _backup_deinterlace_line_vfir (OrcExecutor * ORC_RESTRICT ex)
}
void
-deinterlace_line_vfir (guint8 * d1, const guint8 * s1, const guint8 * s2,
- const guint8 * s3, const guint8 * s4, const guint8 * s5, int n)
+deinterlace_line_vfir (guint8 * ORC_RESTRICT d1, const guint8 * ORC_RESTRICT s1,
+ const guint8 * ORC_RESTRICT s2, const guint8 * ORC_RESTRICT s3,
+ const guint8 * ORC_RESTRICT s4, const guint8 * ORC_RESTRICT s5, int n)
{
OrcExecutor _ex, *ex = &_ex;
static int p_inited = 0;
@@ -314,7 +332,6 @@ deinterlace_line_vfir (guint8 * d1, const guint8 * s1, const guint8 * s2,
if (!p_inited) {
orc_once_mutex_lock ();
if (!p_inited) {
- OrcCompileResult result;
p = orc_program_new ();
orc_program_set_name (p, "deinterlace_line_vfir");
@@ -362,7 +379,7 @@ deinterlace_line_vfir (guint8 * d1, const guint8 * s1, const guint8 * s2,
orc_program_append_2 (p, "convsuswb", 0, ORC_VAR_D1, ORC_VAR_T2,
ORC_VAR_D1, ORC_VAR_D1);
- result = orc_program_compile (p);
+ orc_program_compile (p);
}
p_inited = TRUE;
orc_once_mutex_unlock ();
@@ -386,8 +403,8 @@ deinterlace_line_vfir (guint8 * d1, const guint8 * s1, const guint8 * s2,
/* deinterlace_line_linear */
#ifdef DISABLE_ORC
void
-deinterlace_line_linear (guint8 * d1, const guint8 * s1, const guint8 * s2,
- int n)
+deinterlace_line_linear (guint8 * ORC_RESTRICT d1,
+ const guint8 * ORC_RESTRICT s1, const guint8 * ORC_RESTRICT s2, int n)
{
int i;
orc_int8 *ORC_RESTRICT ptr0;
@@ -447,8 +464,8 @@ _backup_deinterlace_line_linear (OrcExecutor * ORC_RESTRICT ex)
}
void
-deinterlace_line_linear (guint8 * d1, const guint8 * s1, const guint8 * s2,
- int n)
+deinterlace_line_linear (guint8 * ORC_RESTRICT d1,
+ const guint8 * ORC_RESTRICT s1, const guint8 * ORC_RESTRICT s2, int n)
{
OrcExecutor _ex, *ex = &_ex;
static int p_inited = 0;
@@ -458,7 +475,6 @@ deinterlace_line_linear (guint8 * d1, const guint8 * s1, const guint8 * s2,
if (!p_inited) {
orc_once_mutex_lock ();
if (!p_inited) {
- OrcCompileResult result;
p = orc_program_new ();
orc_program_set_name (p, "deinterlace_line_linear");
@@ -470,7 +486,7 @@ deinterlace_line_linear (guint8 * d1, const guint8 * s1, const guint8 * s2,
orc_program_append_2 (p, "avgub", 0, ORC_VAR_D1, ORC_VAR_S1, ORC_VAR_S2,
ORC_VAR_D1);
- result = orc_program_compile (p);
+ orc_program_compile (p);
}
p_inited = TRUE;
orc_once_mutex_unlock ();
@@ -491,8 +507,9 @@ deinterlace_line_linear (guint8 * d1, const guint8 * s1, const guint8 * s2,
/* deinterlace_line_linear_blend */
#ifdef DISABLE_ORC
void
-deinterlace_line_linear_blend (guint8 * d1, const guint8 * s1,
- const guint8 * s2, const guint8 * s3, int n)
+deinterlace_line_linear_blend (guint8 * ORC_RESTRICT d1,
+ const guint8 * ORC_RESTRICT s1, const guint8 * ORC_RESTRICT s2,
+ const guint8 * ORC_RESTRICT s3, int n)
{
int i;
orc_int8 *ORC_RESTRICT ptr0;
@@ -519,7 +536,7 @@ deinterlace_line_linear_blend (guint8 * d1, const guint8 * s1,
ptr6 = (orc_int8 *) s3;
/* 9: loadpw */
- var38.i = 0x00000002; /* 2 or 9.88131e-324f */
+ var38.i = (int) 0x00000002; /* 2 or 9.88131e-324f */
for (i = 0; i < n; i++) {
/* 0: loadb */
@@ -582,7 +599,7 @@ _backup_deinterlace_line_linear_blend (OrcExecutor * ORC_RESTRICT ex)
ptr6 = (orc_int8 *) ex->arrays[6];
/* 9: loadpw */
- var38.i = 0x00000002; /* 2 or 9.88131e-324f */
+ var38.i = (int) 0x00000002; /* 2 or 9.88131e-324f */
for (i = 0; i < n; i++) {
/* 0: loadb */
@@ -616,8 +633,9 @@ _backup_deinterlace_line_linear_blend (OrcExecutor * ORC_RESTRICT ex)
}
void
-deinterlace_line_linear_blend (guint8 * d1, const guint8 * s1,
- const guint8 * s2, const guint8 * s3, int n)
+deinterlace_line_linear_blend (guint8 * ORC_RESTRICT d1,
+ const guint8 * ORC_RESTRICT s1, const guint8 * ORC_RESTRICT s2,
+ const guint8 * ORC_RESTRICT s3, int n)
{
OrcExecutor _ex, *ex = &_ex;
static int p_inited = 0;
@@ -627,7 +645,6 @@ deinterlace_line_linear_blend (guint8 * d1, const guint8 * s1,
if (!p_inited) {
orc_once_mutex_lock ();
if (!p_inited) {
- OrcCompileResult result;
p = orc_program_new ();
orc_program_set_name (p, "deinterlace_line_linear_blend");
@@ -661,7 +678,7 @@ deinterlace_line_linear_blend (guint8 * d1, const guint8 * s1,
orc_program_append_2 (p, "convsuswb", 0, ORC_VAR_D1, ORC_VAR_T1,
ORC_VAR_D1, ORC_VAR_D1);
- result = orc_program_compile (p);
+ orc_program_compile (p);
}
p_inited = TRUE;
orc_once_mutex_unlock ();
@@ -683,9 +700,10 @@ deinterlace_line_linear_blend (guint8 * d1, const guint8 * s1,
/* deinterlace_line_greedy */
#ifdef DISABLE_ORC
void
-deinterlace_line_greedy (orc_uint8 * d1, const orc_uint8 * s1,
- const orc_uint8 * s2, const orc_uint8 * s3, const orc_uint8 * s4, int p1,
- int n)
+deinterlace_line_greedy (orc_uint8 * ORC_RESTRICT d1,
+ const orc_uint8 * ORC_RESTRICT s1, const orc_uint8 * ORC_RESTRICT s2,
+ const orc_uint8 * ORC_RESTRICT s3, const orc_uint8 * ORC_RESTRICT s4,
+ int p1, int n)
{
int i;
orc_int8 *ORC_RESTRICT ptr0;
@@ -728,9 +746,9 @@ deinterlace_line_greedy (orc_uint8 * d1, const orc_uint8 * s1,
ptr7 = (orc_int8 *) s4;
/* 11: loadpb */
- var44 = 0x00000080; /* 128 or 6.32404e-322f */
+ var44 = (int) 0x00000080; /* 128 or 6.32404e-322f */
/* 13: loadpb */
- var45 = 0x00000080; /* 128 or 6.32404e-322f */
+ var45 = (int) 0x00000080; /* 128 or 6.32404e-322f */
/* 21: loadpb */
var46 = p1;
/* 23: loadpb */
@@ -835,9 +853,9 @@ _backup_deinterlace_line_greedy (OrcExecutor * ORC_RESTRICT ex)
ptr7 = (orc_int8 *) ex->arrays[7];
/* 11: loadpb */
- var44 = 0x00000080; /* 128 or 6.32404e-322f */
+ var44 = (int) 0x00000080; /* 128 or 6.32404e-322f */
/* 13: loadpb */
- var45 = 0x00000080; /* 128 or 6.32404e-322f */
+ var45 = (int) 0x00000080; /* 128 or 6.32404e-322f */
/* 21: loadpb */
var46 = ex->params[24];
/* 23: loadpb */
@@ -897,9 +915,10 @@ _backup_deinterlace_line_greedy (OrcExecutor * ORC_RESTRICT ex)
}
void
-deinterlace_line_greedy (orc_uint8 * d1, const orc_uint8 * s1,
- const orc_uint8 * s2, const orc_uint8 * s3, const orc_uint8 * s4, int p1,
- int n)
+deinterlace_line_greedy (orc_uint8 * ORC_RESTRICT d1,
+ const orc_uint8 * ORC_RESTRICT s1, const orc_uint8 * ORC_RESTRICT s2,
+ const orc_uint8 * ORC_RESTRICT s3, const orc_uint8 * ORC_RESTRICT s4,
+ int p1, int n)
{
OrcExecutor _ex, *ex = &_ex;
static int p_inited = 0;
@@ -909,7 +928,6 @@ deinterlace_line_greedy (orc_uint8 * d1, const orc_uint8 * s1,
if (!p_inited) {
orc_once_mutex_lock ();
if (!p_inited) {
- OrcCompileResult result;
p = orc_program_new ();
orc_program_set_name (p, "deinterlace_line_greedy");
@@ -981,7 +999,7 @@ deinterlace_line_greedy (orc_uint8 * d1, const orc_uint8 * s1,
orc_program_append_2 (p, "maxub", 0, ORC_VAR_D1, ORC_VAR_T10, ORC_VAR_T11,
ORC_VAR_D1);
- result = orc_program_compile (p);
+ orc_program_compile (p);
}
p_inited = TRUE;
orc_once_mutex_unlock ();
diff --git a/gst/deinterlace/tvtime-dist.h b/gst/deinterlace/tvtime-dist.h
index a86bd3469..9578a834f 100644
--- a/gst/deinterlace/tvtime-dist.h
+++ b/gst/deinterlace/tvtime-dist.h
@@ -35,6 +35,7 @@ typedef unsigned __int16 orc_uint16;
typedef unsigned __int32 orc_uint32;
typedef unsigned __int64 orc_uint64;
#define ORC_UINT64_C(x) (x##Ui64)
+#define inline __inline
#else
#include <limits.h>
typedef signed char orc_int8;
@@ -57,10 +58,19 @@ typedef union { orc_int16 i; orc_int8 x2[2]; } orc_union16;
typedef union { orc_int32 i; float f; orc_int16 x2[2]; orc_int8 x4[4]; } orc_union32;
typedef union { orc_int64 i; double f; orc_int32 x2[2]; float x2f[2]; orc_int16 x4[4]; } orc_union64;
#endif
-void deinterlace_line_vfir (guint8 * d1, const guint8 * s1, const guint8 * s2, const guint8 * s3, const guint8 * s4, const guint8 * s5, int n);
-void deinterlace_line_linear (guint8 * d1, const guint8 * s1, const guint8 * s2, int n);
-void deinterlace_line_linear_blend (guint8 * d1, const guint8 * s1, const guint8 * s2, const guint8 * s3, int n);
-void deinterlace_line_greedy (orc_uint8 * d1, const orc_uint8 * s1, const orc_uint8 * s2, const orc_uint8 * s3, const orc_uint8 * s4, int p1, int n);
+#ifndef ORC_RESTRICT
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+#define ORC_RESTRICT restrict
+#elif defined(__GNUC__) && __GNUC__ >= 4
+#define ORC_RESTRICT __restrict__
+#else
+#define ORC_RESTRICT
+#endif
+#endif
+void deinterlace_line_vfir (guint8 * ORC_RESTRICT d1, const guint8 * ORC_RESTRICT s1, const guint8 * ORC_RESTRICT s2, const guint8 * ORC_RESTRICT s3, const guint8 * ORC_RESTRICT s4, const guint8 * ORC_RESTRICT s5, int n);
+void deinterlace_line_linear (guint8 * ORC_RESTRICT d1, const guint8 * ORC_RESTRICT s1, const guint8 * ORC_RESTRICT s2, int n);
+void deinterlace_line_linear_blend (guint8 * ORC_RESTRICT d1, const guint8 * ORC_RESTRICT s1, const guint8 * ORC_RESTRICT s2, const guint8 * ORC_RESTRICT s3, int n);
+void deinterlace_line_greedy (orc_uint8 * ORC_RESTRICT d1, const orc_uint8 * ORC_RESTRICT s1, const orc_uint8 * ORC_RESTRICT s2, const orc_uint8 * ORC_RESTRICT s3, const orc_uint8 * ORC_RESTRICT s4, int p1, int n);
#ifdef __cplusplus
}
diff --git a/gst/deinterlace/tvtime/greedyh.c b/gst/deinterlace/tvtime/greedyh.c
index bd2794cb3..d1e4fd6b1 100644
--- a/gst/deinterlace/tvtime/greedyh.c
+++ b/gst/deinterlace/tvtime/greedyh.c
@@ -749,7 +749,7 @@ deinterlace_frame_di_greedyh_packed (GstDeinterlaceMethod * method,
break;
default:
g_assert_not_reached ();
- break;
+ return;
}
// copy first even line no matter what, and the first odd line if we're
diff --git a/gst/effectv/Makefile.am b/gst/effectv/Makefile.am
index e0c280309..2fe3152b1 100644
--- a/gst/effectv/Makefile.am
+++ b/gst/effectv/Makefile.am
@@ -22,3 +22,17 @@ libgsteffectv_la_LIBTOOLFLAGS = --tag=disable-static
noinst_HEADERS = gsteffectv.h gstaging.h gstdice.h gstedge.h \
gstquark.h gstrev.h gstshagadelic.h gstvertigo.h gstwarp.h gstop.h \
gstradioac.h gststreak.h gstripple.h
+
+Android.mk: Makefile.am $(BUILT_SOURCES)
+ androgenizer \
+ -:PROJECT libgsteffectv -:SHARED libgsteffectv \
+ -:TAGS eng debug \
+ -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
+ -:SOURCES $(libgsteffectv_la_SOURCES) \
+ -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgsteffectv_la_CFLAGS) \
+ -:LDFLAGS $(libgsteffectv_la_LDFLAGS) \
+ $(libgsteffectv_la_LIBADD) \
+ -ldl \
+ -:PASSTHROUGH LOCAL_ARM_MODE:=arm \
+ LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \
+ > $@
diff --git a/gst/effectv/gstedge.c b/gst/effectv/gstedge.c
index db109bfd5..f4b776297 100644
--- a/gst/effectv/gstedge.c
+++ b/gst/effectv/gstedge.c
@@ -108,7 +108,7 @@ gst_edgetv_transform (GstBaseTransform * trans, GstBuffer * in, GstBuffer * out)
guint32 *src, *dest;
guint32 p, q;
guint32 v0, v1, v2, v3;
- gint height, width, map_height, map_width;
+ gint width, map_height, map_width;
gint video_width_margin;
guint32 *map;
GstFlowReturn ret = GST_FLOW_OK;
@@ -118,7 +118,6 @@ gst_edgetv_transform (GstBaseTransform * trans, GstBuffer * in, GstBuffer * out)
GST_OBJECT_LOCK (filter);
map = filter->map;
- height = filter->height;
width = filter->width;
map_height = filter->map_height;
map_width = filter->map_width;
diff --git a/gst/equalizer/Makefile.am b/gst/equalizer/Makefile.am
index 0ab490503..b3b86633e 100644
--- a/gst/equalizer/Makefile.am
+++ b/gst/equalizer/Makefile.am
@@ -21,3 +21,16 @@ preset_DATA = GstIirEqualizer3Bands.prs GstIirEqualizer10Bands.prs
EXTRA_DIST = $(preset_DATA)
+Android.mk: Makefile.am $(BUILT_SOURCES)
+ androgenizer \
+ -:PROJECT libgstequalizer -:SHARED libgstequalizer \
+ -:TAGS eng debug \
+ -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
+ -:SOURCES $(libgstequalizer_la_SOURCES) \
+ -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstequalizer_la_CFLAGS) \
+ -:LDFLAGS $(libgstequalizer_la_LDFLAGS) \
+ $(libgstequalizer_la_LIBADD) \
+ -ldl \
+ -:PASSTHROUGH LOCAL_ARM_MODE:=arm \
+ LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \
+ > $@
diff --git a/gst/flv/Makefile.am b/gst/flv/Makefile.am
index ab08cdd9e..93e1de1ce 100644
--- a/gst/flv/Makefile.am
+++ b/gst/flv/Makefile.am
@@ -8,3 +8,17 @@ libgstflv_la_SOURCES = gstflvdemux.c gstflvmux.c
libgstflv_la_LIBTOOLFLAGS = --tag=disable-static
noinst_HEADERS = gstflvdemux.h gstflvmux.h
+
+Android.mk: Makefile.am $(BUILT_SOURCES)
+ androgenizer \
+ -:PROJECT libgstflv -:SHARED libgstflv \
+ -:TAGS eng debug \
+ -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
+ -:SOURCES $(libgstflv_la_SOURCES) \
+ -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstflv_la_CFLAGS) \
+ -:LDFLAGS $(libgstflv_la_LDFLAGS) \
+ $(libgstflv_la_LIBADD) \
+ -ldl \
+ -:PASSTHROUGH LOCAL_ARM_MODE:=arm \
+ LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \
+ > $@
diff --git a/gst/flv/gstflvdemux.c b/gst/flv/gstflvdemux.c
index 820f689ec..f989ddedf 100644
--- a/gst/flv/gstflvdemux.c
+++ b/gst/flv/gstflvdemux.c
@@ -202,12 +202,15 @@ gst_flv_demux_check_seekability (GstFlvDemux * demux)
query = gst_query_new_seeking (GST_FORMAT_BYTES);
if (!gst_pad_peer_query (demux->sinkpad, query)) {
GST_DEBUG_OBJECT (demux, "seeking query failed");
+ gst_query_unref (query);
return;
}
gst_query_parse_seeking (query, NULL, &demux->upstream_seekable,
&start, &stop);
+ gst_query_unref (query);
+
/* try harder to query upstream size if we didn't get it the first time */
if (demux->upstream_seekable && stop == -1) {
GstFormat fmt = GST_FORMAT_BYTES;
@@ -321,6 +324,12 @@ gst_flv_demux_parse_metadata_item (GstFlvDemux * demux, GstByteReader * reader,
} else if (!strcmp (tag_name, "AspectRatioY")) {
demux->par_y = d;
demux->got_par = TRUE;
+ } else if (!strcmp (tag_name, "width")) {
+ demux->w = d;
+ } else if (!strcmp (tag_name, "height")) {
+ demux->h = d;
+ } else if (!strcmp (tag_name, "framerate")) {
+ demux->framerate = d;
} else {
GST_INFO_OBJECT (demux, "Tag \'%s\' not handled", tag_name);
}
@@ -1074,6 +1083,25 @@ gst_flv_demux_video_negotiate (GstFlvDemux * demux, guint32 codec_tag)
gst_caps_set_simple (caps, "pixel-aspect-ratio", GST_TYPE_FRACTION,
demux->par_x, demux->par_y, NULL);
+ if (G_LIKELY (demux->w)) {
+ gst_caps_set_simple (caps, "width", G_TYPE_INT, demux->w, NULL);
+ }
+
+ if (G_LIKELY (demux->h)) {
+ gst_caps_set_simple (caps, "height", G_TYPE_INT, demux->h, NULL);
+ }
+
+ if (G_LIKELY (demux->framerate)) {
+ gint num = 0, den = 0;
+
+ gst_util_double_to_fraction (demux->framerate, &num, &den);
+ GST_DEBUG_OBJECT (demux->video_pad,
+ "fps to be used on caps %f (as a fraction = %d/%d)", demux->framerate,
+ num, den);
+
+ gst_caps_set_simple (caps, "framerate", GST_TYPE_FRACTION, num, den, NULL);
+ }
+
if (demux->video_codec_data) {
gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER,
demux->video_codec_data, NULL);
@@ -1602,6 +1630,7 @@ gst_flv_demux_cleanup (GstFlvDemux * demux)
gst_segment_init (&demux->segment, GST_FORMAT_TIME);
demux->w = demux->h = 0;
+ demux->framerate = 0.0;
demux->par_x = demux->par_y = 1;
demux->video_offset = 0;
demux->audio_offset = 0;
@@ -2414,7 +2443,7 @@ flv_demux_handle_seek_push (GstFlvDemux * demux, GstEvent * event)
GstSeekType start_type, stop_type;
gint64 start, stop;
gdouble rate;
- gboolean update, flush, keyframe, ret;
+ gboolean update, flush, ret;
GstSegment seeksegment;
gst_event_parse_seek (event, &rate, &format, &flags,
@@ -2425,7 +2454,6 @@ flv_demux_handle_seek_push (GstFlvDemux * demux, GstEvent * event)
flush = !!(flags & GST_SEEK_FLAG_FLUSH);
/* FIXME : the keyframe flag is never used ! */
- keyframe = !!(flags & GST_SEEK_FLAG_KEY_UNIT);
/* Work on a copy until we are sure the seek succeeded. */
memcpy (&seeksegment, &demux->segment, sizeof (GstSegment));
@@ -2574,7 +2602,7 @@ gst_flv_demux_handle_seek_pull (GstFlvDemux * demux, GstEvent * event,
GstSeekType start_type, stop_type;
gint64 start, stop;
gdouble rate;
- gboolean update, flush, keyframe, ret = FALSE;
+ gboolean update, flush, ret = FALSE;
GstSegment seeksegment;
gst_event_parse_seek (event, &rate, &format, &flags,
@@ -2591,7 +2619,6 @@ gst_flv_demux_handle_seek_pull (GstFlvDemux * demux, GstEvent * event,
flush = !!(flags & GST_SEEK_FLAG_FLUSH);
/* FIXME : the keyframe flag is never used */
- keyframe = !!(flags & GST_SEEK_FLAG_KEY_UNIT);
if (flush) {
/* Flush start up and downstream to make sure data flow and loops are
diff --git a/gst/flv/gstflvdemux.h b/gst/flv/gstflvdemux.h
index 10ff306a2..60083e867 100644
--- a/gst/flv/gstflvdemux.h
+++ b/gst/flv/gstflvdemux.h
@@ -109,6 +109,7 @@ struct _GstFlvDemux
gboolean got_par;
GstBuffer * video_codec_data;
GstClockTime video_start;
+ gdouble framerate;
gboolean random_access;
gboolean need_header;
diff --git a/gst/flx/Makefile.am b/gst/flx/Makefile.am
index 38ed6818d..01d8bd85f 100644
--- a/gst/flx/Makefile.am
+++ b/gst/flx/Makefile.am
@@ -8,3 +8,17 @@ libgstflxdec_la_LIBTOOLFLAGS = --tag=disable-static
noinst_HEADERS = flx_fmt.h flx_color.h gstflxdec.h
+Android.mk: Makefile.am $(BUILT_SOURCES)
+ androgenizer \
+ -:PROJECT libgstflxdec -:SHARED libgstflxdec \
+ -:TAGS eng debug \
+ -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
+ -:SOURCES $(libgstflxdec_la_SOURCES) \
+ $(nodist_libgstflxdec_la_SOURCES) \
+ -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstflxdec_la_CFLAGS) \
+ -:LDFLAGS $(libgstflxdec_la_LDFLAGS) \
+ $(libgstflxdec_la_LIBADD) \
+ -ldl \
+ -:PASSTHROUGH LOCAL_ARM_MODE:=arm \
+ LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \
+ > $@
diff --git a/gst/goom/Makefile.am b/gst/goom/Makefile.am
index 4e628e997..500f0a809 100644
--- a/gst/goom/Makefile.am
+++ b/gst/goom/Makefile.am
@@ -46,3 +46,16 @@ EXTRA_DIST = $(PPC_FILES) $(MMX_FILES)
.NOTPARALLEL:
+Android.mk: Makefile.am $(BUILT_SOURCES)
+ androgenizer \
+ -:PROJECT libgstgoom -:SHARED libgstgoom \
+ -:TAGS eng debug \
+ -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
+ -:SOURCES $(libgstgoom_la_SOURCES) \
+ -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstgoom_la_CFLAGS) \
+ -:LDFLAGS $(libgstgoom_la_LDFLAGS) \
+ $(libgstgoom_la_LIBADD) \
+ -ldl \
+ -:PASSTHROUGH LOCAL_ARM_MODE:=arm \
+ LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \
+ > $@
diff --git a/gst/goom2k1/Makefile.am b/gst/goom2k1/Makefile.am
index aea0e0480..6b2ddfd41 100644
--- a/gst/goom2k1/Makefile.am
+++ b/gst/goom2k1/Makefile.am
@@ -13,3 +13,17 @@ libgstgoom2k1_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
libgstgoom2k1_la_LIBTOOLFLAGS = --tag=disable-static
EXTRA_DIST = filters.c
+
+Android.mk: Makefile.am $(BUILT_SOURCES)
+ androgenizer \
+ -:PROJECT libgstgoom2k1 -:SHARED libgstgoom2k1 \
+ -:TAGS eng debug \
+ -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
+ -:SOURCES $(libgstgoom2k1_la_SOURCES) \
+ -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstgoom2k1_la_CFLAGS) \
+ -:LDFLAGS $(libgstgoom2k1_la_LDFLAGS) \
+ $(libgstgoom2k1_la_LIBADD) \
+ -ldl \
+ -:PASSTHROUGH LOCAL_ARM_MODE:=arm \
+ LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \
+ > $@
diff --git a/gst/icydemux/Makefile.am b/gst/icydemux/Makefile.am
index 167dd628b..b7f2c66af 100644
--- a/gst/icydemux/Makefile.am
+++ b/gst/icydemux/Makefile.am
@@ -7,3 +7,17 @@ libgsticydemux_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
libgsticydemux_la_LIBTOOLFLAGS = --tag=disable-static
noinst_HEADERS = gsticydemux.h
+
+Android.mk: Makefile.am $(BUILT_SOURCES)
+ androgenizer \
+ -:PROJECT libgsticydemux -:SHARED libgsticydemux \
+ -:TAGS eng debug \
+ -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
+ -:SOURCES $(libgsticydemux_la_SOURCES) \
+ -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgsticydemux_la_CFLAGS) \
+ -:LDFLAGS $(libgsticydemux_la_LDFLAGS) \
+ $(libgsticydemux_la_LIBADD) \
+ -ldl \
+ -:PASSTHROUGH LOCAL_ARM_MODE:=arm \
+ LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \
+ > $@
diff --git a/gst/id3demux/Makefile.am b/gst/id3demux/Makefile.am
index 3f004437d..823cb7765 100644
--- a/gst/id3demux/Makefile.am
+++ b/gst/id3demux/Makefile.am
@@ -8,3 +8,17 @@ libgstid3demux_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
libgstid3demux_la_LIBTOOLFLAGS = --tag=disable-static
noinst_HEADERS = gstid3demux.h id3tags.h
+
+Android.mk: Makefile.am $(BUILT_SOURCES)
+ androgenizer \
+ -:PROJECT libgstid3demux -:SHARED libgstid3demux \
+ -:TAGS eng debug \
+ -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
+ -:SOURCES $(libgstid3demux_la_SOURCES) \
+ -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(CPPFLAGS) $(libgstid3demux_la_CFLAGS) \
+ -:LDFLAGS $(libgstid3demux_la_LDFLAGS) \
+ $(libgstid3demux_la_LIBADD) \
+ -ldl \
+ -:PASSTHROUGH LOCAL_ARM_MODE:=arm \
+ LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \
+ > $@
diff --git a/gst/imagefreeze/Makefile.am b/gst/imagefreeze/Makefile.am
index af96a98c1..7aa861431 100644
--- a/gst/imagefreeze/Makefile.am
+++ b/gst/imagefreeze/Makefile.am
@@ -9,3 +9,16 @@ libgstimagefreeze_la_LIBTOOLFLAGS = --tag=disable-static
noinst_HEADERS = gstimagefreeze.h
+Android.mk: Makefile.am $(BUILT_SOURCES)
+ androgenizer \
+ -:PROJECT libgstimagefreeze -:SHARED libgstimagefreeze \
+ -:TAGS eng debug \
+ -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
+ -:SOURCES $(libgstimagefreeze_la_SOURCES) \
+ -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstimagefreeze_la_CFLAGS) \
+ -:LDFLAGS $(libgstimagefreeze_la_LDFLAGS) \
+ $(libgstimagefreeze_la_LIBADD) \
+ -ldl \
+ -:PASSTHROUGH LOCAL_ARM_MODE:=arm \
+ LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \
+ > $@
diff --git a/gst/imagefreeze/gstimagefreeze.c b/gst/imagefreeze/gstimagefreeze.c
index d6a3a9cf3..3e122adca 100644
--- a/gst/imagefreeze/gstimagefreeze.c
+++ b/gst/imagefreeze/gstimagefreeze.c
@@ -608,7 +608,7 @@ gst_image_freeze_src_event (GstPad * pad, GstEvent * event)
&stop_type, &stop);
gst_event_unref (event);
- flush = ! !(flags & GST_SEEK_FLAG_FLUSH);
+ flush = !!(flags & GST_SEEK_FLAG_FLUSH);
if (format != GST_FORMAT_TIME && format != GST_FORMAT_DEFAULT) {
GST_ERROR_OBJECT (pad, "Seek in invalid format: %s",
@@ -744,7 +744,7 @@ gst_image_freeze_src_loop (GstPad * pad)
GstImageFreeze *self = GST_IMAGE_FREEZE (GST_PAD_PARENT (pad));
GstBuffer *buffer;
guint64 offset;
- GstClockTime timestamp, timestamp_end, duration;
+ GstClockTime timestamp, timestamp_end;
gint64 cstart, cstop;
gboolean in_seg, eos;
@@ -800,11 +800,9 @@ gst_image_freeze_src_loop (GstPad * pad)
timestamp_end =
gst_util_uint64_scale (offset + 1, self->fps_d * GST_SECOND,
self->fps_n);
- duration = timestamp_end - timestamp;
} else {
timestamp = self->segment.start;
timestamp_end = GST_CLOCK_TIME_NONE;
- duration = GST_CLOCK_TIME_NONE;
}
eos = (self->fps_n == 0 && offset > 0) ||
diff --git a/gst/interleave/Makefile.am b/gst/interleave/Makefile.am
index d1d0b8227..0a2d2d8d5 100644
--- a/gst/interleave/Makefile.am
+++ b/gst/interleave/Makefile.am
@@ -8,3 +8,17 @@ libgstinterleave_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
libgstinterleave_la_LIBTOOLFLAGS = --tag=disable-static
noinst_HEADERS = plugin.h interleave.h deinterleave.h
+
+Android.mk: Makefile.am $(BUILT_SOURCES)
+ androgenizer \
+ -:PROJECT libgstinterleave -:SHARED libgstinterleave \
+ -:TAGS eng debug \
+ -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
+ -:SOURCES $(libgstinterleave_la_SOURCES) \
+ -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstinterleave_la_CFLAGS) \
+ -:LDFLAGS $(libgstinterleave_la_LDFLAGS) \
+ $(libgstinterleave_la_LIBADD) \
+ -ldl \
+ -:PASSTHROUGH LOCAL_ARM_MODE:=arm \
+ LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \
+ > $@
diff --git a/gst/law/Makefile.am b/gst/law/Makefile.am
index f841f6640..16bff25b7 100644
--- a/gst/law/Makefile.am
+++ b/gst/law/Makefile.am
@@ -13,3 +13,28 @@ libgstmulaw_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
libgstmulaw_la_LIBTOOLFLAGS = --tag=disable-static
noinst_HEADERS = mulaw-conversion.h alaw-encode.h alaw-decode.h mulaw-encode.h mulaw-decode.h
+
+Android.mk: Makefile.am $(BUILT_SOURCES)
+ androgenizer \
+ -:PROJECT libgstalaw -:SHARED libgstalaw \
+ -:TAGS eng debug \
+ -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
+ -:SOURCES $(libgstalaw_la_SOURCES) \
+ $(nodist_libgstalaw_la_SOURCES) \
+ -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstalaw_la_CFLAGS) \
+ -:LDFLAGS $(libgstalaw_la_LDFLAGS) \
+ $(libgstalaw_la_LIBADD) \
+ -ldl \
+ -:PASSTHROUGH LOCAL_ARM_MODE:=arm \
+ LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \
+ -:SHARED libgstmulaw \
+ -:TAGS eng debug \
+ -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
+ -:SOURCES $(libgstmulaw_la_SOURCES) \
+ -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstmulaw_la_CFLAGS) \
+ -:LDFLAGS $(libgstmulaw_la_LDFLAGS) \
+ $(libgstmulaw_la_LIBADD) \
+ -ldl \
+ -:PASSTHROUGH LOCAL_ARM_MODE:=arm \
+ LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \
+ > $@
diff --git a/gst/level/Makefile.am b/gst/level/Makefile.am
index cd9b5fbc3..047e196ad 100644
--- a/gst/level/Makefile.am
+++ b/gst/level/Makefile.am
@@ -8,3 +8,17 @@ libgstlevel_la_LIBTOOLFLAGS = --tag=disable-static
noinst_HEADERS = gstlevel.h
+
+Android.mk: Makefile.am $(BUILT_SOURCES)
+ androgenizer \
+ -:PROJECT libgstlevel -:SHARED libgstlevel \
+ -:TAGS eng debug \
+ -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
+ -:SOURCES $(libgstlevel_la_SOURCES) \
+ -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstlevel_la_CFLAGS) \
+ -:LDFLAGS $(libgstlevel_la_LDFLAGS) \
+ $(libgstlevel_la_LIBADD) \
+ -ldl \
+ -:PASSTHROUGH LOCAL_ARM_MODE:=arm \
+ LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \
+ > $@
diff --git a/gst/matroska/Makefile.am b/gst/matroska/Makefile.am
index 5efbf4eb0..195c68057 100644
--- a/gst/matroska/Makefile.am
+++ b/gst/matroska/Makefile.am
@@ -39,3 +39,18 @@ libgstmatroska_la_LIBADD = \
$(LIBM)
libgstmatroska_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
libgstmatroska_la_LIBTOOLFLAGS = --tag=disable-static
+
+
+Android.mk: Makefile.am $(BUILT_SOURCES)
+ androgenizer \
+ -:PROJECT libgstmatroska -:SHARED libgstmatroska \
+ -:TAGS eng debug \
+ -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
+ -:SOURCES $(libgstmatroska_la_SOURCES) \
+ -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(CPPFLAGS) $(libgstmatroska_la_CFLAGS) \
+ -:LDFLAGS $(libgstmatroska_la_LDFLAGS) \
+ $(libgstmatroska_la_LIBADD) \
+ -ldl \
+ -:PASSTHROUGH LOCAL_ARM_MODE:=arm \
+ LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \
+ > $@
diff --git a/gst/matroska/matroska-demux.c b/gst/matroska/matroska-demux.c
index aa714f6a0..ba4ceb27f 100644
--- a/gst/matroska/matroska-demux.c
+++ b/gst/matroska/matroska-demux.c
@@ -1070,7 +1070,6 @@ gst_matroska_decode_content_encodings (GArray * encodings)
for (i = 0; i < encodings->len; i++) {
GstMatroskaTrackEncoding *enc =
&g_array_index (encodings, GstMatroskaTrackEncoding, i);
- GstMatroskaTrackEncoding *enc2;
guint8 *data = NULL;
guint size;
@@ -1085,8 +1084,6 @@ gst_matroska_decode_content_encodings (GArray * encodings)
if (i + 1 >= encodings->len)
return GST_FLOW_ERROR;
- enc2 = &g_array_index (encodings, GstMatroskaTrackEncoding, i + 1);
-
if (enc->comp_settings_length == 0)
continue;
@@ -2689,8 +2686,8 @@ gst_matroska_demux_handle_seek_event (GstMatroskaDemux * demux,
entry->pos + demux->ebml_segment_start);
}
- flush = ! !(flags & GST_SEEK_FLAG_FLUSH);
- keyunit = ! !(flags & GST_SEEK_FLAG_KEY_UNIT);
+ flush = !!(flags & GST_SEEK_FLAG_FLUSH);
+ keyunit = !!(flags & GST_SEEK_FLAG_KEY_UNIT);
if (flush) {
GST_DEBUG_OBJECT (demux, "Starting flush");
@@ -6317,6 +6314,31 @@ gst_matroska_demux_sink_activate_pull (GstPad * sinkpad, gboolean active)
return TRUE;
}
+static void
+gst_duration_to_fraction (guint64 duration, gint * dest_n, gint * dest_d)
+{
+ static const int common_den[] = { 1, 2, 3, 4, 1001 };
+ int n, d;
+ int i;
+ guint64 a;
+
+ for (i = 0; i < G_N_ELEMENTS (common_den); i++) {
+ d = common_den[i];
+ n = floor (0.5 + (d * 1e9) / duration);
+ a = gst_util_uint64_scale_int (1000000000, d, n);
+ if (duration >= a - 1 && duration <= a + 1) {
+ goto out;
+ }
+ }
+
+ gst_util_double_to_fraction (1e9 / duration, &n, &d);
+
+out:
+ /* set results */
+ *dest_n = n;
+ *dest_d = d;
+}
+
static GstCaps *
gst_matroska_demux_video_caps (GstMatroskaTrackVideoContext *
videocontext, const gchar * codec_id, guint8 * data, guint size,
@@ -6503,6 +6525,10 @@ gst_matroska_demux_video_caps (GstMatroskaTrackVideoContext *
gst_caps_set_simple (caps, "stream-format", G_TYPE_STRING, "avc",
"alignment", G_TYPE_STRING, "au", NULL);
+ } else {
+ GST_WARNING ("No codec data found, assuming output is byte-stream");
+ gst_caps_set_simple (caps, "stream-format", G_TYPE_STRING, "byte-stream",
+ NULL);
}
*codec_name = g_strdup ("H264");
} else if ((!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_REALVIDEO1)) ||
@@ -6608,21 +6634,15 @@ gst_matroska_demux_video_caps (GstMatroskaTrackVideoContext *
g_value_unset (&fps_double);
g_value_unset (&fps_fraction);
} else if (context->default_duration > 0) {
- GValue fps_double = { 0, };
- GValue fps_fraction = { 0, };
+ int fps_n, fps_d;
- g_value_init (&fps_double, G_TYPE_DOUBLE);
- g_value_init (&fps_fraction, GST_TYPE_FRACTION);
- g_value_set_double (&fps_double, (gdouble) GST_SECOND /
- gst_guint64_to_gdouble (context->default_duration));
- g_value_transform (&fps_double, &fps_fraction);
+ gst_duration_to_fraction (context->default_duration, &fps_n, &fps_d);
- GST_DEBUG ("using default duration %" G_GUINT64_FORMAT,
- context->default_duration);
+ GST_INFO ("using default duration %" G_GUINT64_FORMAT
+ " framerate %d/%d", context->default_duration, fps_n, fps_d);
- gst_structure_set_value (structure, "framerate", &fps_fraction);
- g_value_unset (&fps_double);
- g_value_unset (&fps_fraction);
+ gst_structure_set (structure, "framerate", GST_TYPE_FRACTION,
+ fps_n, fps_d, NULL);
} else {
/* sort of a hack to get most codecs to support,
* even if the default_duration is missing */
diff --git a/gst/matroska/matroska-mux.c b/gst/matroska/matroska-mux.c
index 7be224555..7f94f1871 100644
--- a/gst/matroska/matroska-mux.c
+++ b/gst/matroska/matroska-mux.c
@@ -494,7 +494,7 @@ gst_matroska_pad_reset (GstMatroskaPad * collect_pad, gboolean full)
break;
default:
g_assert_not_reached ();
- break;
+ return;
}
context->type = type;
diff --git a/gst/matroska/matroska-parse.c b/gst/matroska/matroska-parse.c
index 88e0e152f..24a95a9cc 100644
--- a/gst/matroska/matroska-parse.c
+++ b/gst/matroska/matroska-parse.c
@@ -228,8 +228,7 @@ gst_matroska_parse_init (GstMatroskaParse * parse,
gst_pad_set_query_function (parse->srcpad,
GST_DEBUG_FUNCPTR (gst_matroska_parse_handle_src_query));
gst_pad_use_fixed_caps (parse->srcpad);
- gst_pad_set_caps (parse->srcpad, gst_caps_new_simple ("video/x-matroska",
- NULL));
+
gst_element_add_pad (GST_ELEMENT (parse), parse->srcpad);
/* initial stream no. */
@@ -961,7 +960,6 @@ gst_matroska_decode_content_encodings (GArray * encodings)
for (i = 0; i < encodings->len; i++) {
GstMatroskaTrackEncoding *enc =
&g_array_index (encodings, GstMatroskaTrackEncoding, i);
- GstMatroskaTrackEncoding *enc2;
guint8 *data = NULL;
guint size;
@@ -976,8 +974,6 @@ gst_matroska_decode_content_encodings (GArray * encodings)
if (i + 1 >= encodings->len)
return GST_FLOW_ERROR;
- enc2 = &g_array_index (encodings, GstMatroskaTrackEncoding, i + 1);
-
if (enc->comp_settings_length == 0)
continue;
@@ -3463,9 +3459,6 @@ gst_matroska_parse_parse_blockgroup_or_simpleblock (GstMatroskaParse * parse,
gint64 time = 0;
gint flags = 0;
gint64 referenceblock = 0;
- gint64 offset;
-
- offset = gst_ebml_read_get_offset (ebml);
while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
if (!is_simpleblock) {
@@ -4071,11 +4064,10 @@ gst_matroska_parse_parse_contents_seekentry (GstMatroskaParse * parse,
case GST_MATROSKA_ID_ATTACHMENTS:
case GST_MATROSKA_ID_CHAPTERS:
{
- guint64 before_pos, length;
+ guint64 length;
/* remember */
length = gst_matroska_parse_get_length (parse);
- before_pos = parse->offset;
if (length == (guint64) - 1) {
GST_DEBUG_OBJECT (parse, "no upstream length, skipping SeakHead entry");
diff --git a/gst/monoscope/Makefile.am b/gst/monoscope/Makefile.am
index 7430c0e0d..f86946979 100644
--- a/gst/monoscope/Makefile.am
+++ b/gst/monoscope/Makefile.am
@@ -9,3 +9,16 @@ libgstmonoscope_la_LIBADD = $(GST_LIBS) $(GST_BASE_LIBS)
libgstmonoscope_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
libgstmonoscope_la_LIBTOOLFLAGS = --tag=disable-static
+Android.mk: Makefile.am $(BUILT_SOURCES)
+ androgenizer \
+ -:PROJECT libgstmonoscope -:SHARED libgstmonoscope \
+ -:TAGS eng debug \
+ -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
+ -:SOURCES $(libgstmonoscope_la_SOURCES) \
+ -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstmonoscope_la_CFLAGS) \
+ -:LDFLAGS $(libgstmonoscope_la_LDFLAGS) \
+ $(libgstmonoscope_la_LIBADD) \
+ -ldl \
+ -:PASSTHROUGH LOCAL_ARM_MODE:=arm \
+ LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \
+ > $@
diff --git a/gst/multifile/Makefile.am b/gst/multifile/Makefile.am
index 785e09c3b..52e33bc09 100644
--- a/gst/multifile/Makefile.am
+++ b/gst/multifile/Makefile.am
@@ -9,3 +9,17 @@ libgstmultifile_la_LIBTOOLFLAGS = --tag=disable-static
noinst_HEADERS = gstmultifilesrc.h gstmultifilesink.h
+
+Android.mk: Makefile.am $(BUILT_SOURCES)
+ androgenizer \
+ -:PROJECT libgstmultifile -:SHARED libgstmultifile \
+ -:TAGS eng debug \
+ -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
+ -:SOURCES $(libgstmultifile_la_SOURCES) \
+ -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstmultifile_la_CFLAGS) \
+ -:LDFLAGS $(libgstmultifile_la_LDFLAGS) \
+ $(libgstmultifile_la_LIBADD) \
+ -ldl \
+ -:PASSTHROUGH LOCAL_ARM_MODE:=arm \
+ LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \
+ > $@
diff --git a/gst/multipart/Makefile.am b/gst/multipart/Makefile.am
index 85f462fa9..8ec931e13 100644
--- a/gst/multipart/Makefile.am
+++ b/gst/multipart/Makefile.am
@@ -8,3 +8,17 @@ libgstmultipart_la_LIBTOOLFLAGS = --tag=disable-static
noinst_HEADERS = multipartdemux.h multipartmux.h
+
+Android.mk: Makefile.am $(BUILT_SOURCES)
+ androgenizer \
+ -:PROJECT libgstmultipart -:SHARED libgstmultipart \
+ -:TAGS eng debug \
+ -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
+ -:SOURCES $(libgstmultipart_la_SOURCES) \
+ -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstmultipart_la_CFLAGS) \
+ -:LDFLAGS $(libgstmultipart_la_LDFLAGS) \
+ $(libgstmultipart_la_LIBADD) \
+ -ldl \
+ -:PASSTHROUGH LOCAL_ARM_MODE:=arm \
+ LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \
+ > $@
diff --git a/gst/qtdemux/Makefile.am b/gst/qtdemux/Makefile.am
deleted file mode 100644
index ecfa0daad..000000000
--- a/gst/qtdemux/Makefile.am
+++ /dev/null
@@ -1,26 +0,0 @@
-
-plugin_LTLIBRARIES = libgstqtdemux.la
-
-libgstqtdemux_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS)
-libgstqtdemux_la_LIBADD = \
- $(GST_PLUGINS_BASE_LIBS) \
- -lgstriff-@GST_MAJORMINOR@ \
- -lgstaudio-@GST_MAJORMINOR@ \
- -lgstrtp-@GST_MAJORMINOR@ \
- -lgsttag-@GST_MAJORMINOR@ \
- -lgstpbutils-@GST_MAJORMINOR@ \
- $(GST_BASE_LIBS) $(GST_LIBS) $(ZLIB_LIBS)
-libgstqtdemux_la_LDFLAGS = ${GST_PLUGIN_LDFLAGS}
-libgstqtdemux_la_SOURCES = quicktime.c gstrtpxqtdepay.c \
- qtdemux.c qtdemux_types.c qtdemux_dump.c qtdemux_lang.c
-libgstqtdemux_la_LIBTOOLFLAGS = --tag=disable-static
-
-noinst_HEADERS = \
- qtatomparser.h \
- qtdemux.h \
- qtdemux_types.h \
- qtdemux_dump.h \
- qtdemux_fourcc.h \
- qtdemux_lang.h \
- qtpalette.h \
- gstrtpxqtdepay.h
diff --git a/gst/qtdemux/LEGAL b/gst/quicktime/LEGAL
index 5af6e8f92..5af6e8f92 100644
--- a/gst/qtdemux/LEGAL
+++ b/gst/quicktime/LEGAL
diff --git a/gst/quicktime/Makefile.am b/gst/quicktime/Makefile.am
new file mode 100644
index 000000000..00cc1678a
--- /dev/null
+++ b/gst/quicktime/Makefile.am
@@ -0,0 +1,51 @@
+
+plugin_LTLIBRARIES = libgstqtdemux.la
+
+libgstqtdemux_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS)
+libgstqtdemux_la_LIBADD = \
+ $(GST_PLUGINS_BASE_LIBS) \
+ -lgstriff-@GST_MAJORMINOR@ \
+ -lgstaudio-@GST_MAJORMINOR@ \
+ -lgstrtp-@GST_MAJORMINOR@ \
+ -lgsttag-@GST_MAJORMINOR@ \
+ -lgstpbutils-@GST_MAJORMINOR@ \
+ $(GST_BASE_LIBS) $(GST_LIBS) $(ZLIB_LIBS)
+libgstqtdemux_la_LDFLAGS = ${GST_PLUGIN_LDFLAGS}
+libgstqtdemux_la_SOURCES = quicktime.c gstrtpxqtdepay.c \
+ qtdemux.c qtdemux_types.c qtdemux_dump.c qtdemux_lang.c \
+ gstqtmux.c gstqtmoovrecover.c atoms.c atomsrecovery.c descriptors.c \
+ properties.c gstqtmuxmap.c
+libgstqtdemux_la_LIBTOOLFLAGS = --tag=disable-static
+
+noinst_HEADERS = \
+ qtatomparser.h \
+ qtdemux.h \
+ qtdemux_types.h \
+ qtdemux_dump.h \
+ qtdemux_fourcc.h \
+ qtdemux_lang.h \
+ qtpalette.h \
+ gstrtpxqtdepay.h \
+ gstqtmux.h \
+ gstqtmoovrecover.h \
+ atoms.h \
+ atomsrecovery.h \
+ descriptors.h \
+ properties.h \
+ fourcc.h \
+ ftypcc.h \
+ gstqtmuxmap.h
+
+Android.mk: Makefile.am $(BUILT_SOURCES)
+ androgenizer \
+ -:PROJECT libgstqtdemux -:SHARED libgstqtdemux \
+ -:TAGS eng debug \
+ -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
+ -:SOURCES $(libgstqtdemux_la_SOURCES) \
+ -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(CPPFLAGS) $(libgstqtdemux_la_CFLAGS) \
+ -:LDFLAGS $(libgstqtdemux_la_LDFLAGS) \
+ $(libgstqtdemux_la_LIBADD) \
+ -ldl \
+ -:PASSTHROUGH LOCAL_ARM_MODE:=arm \
+ LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \
+ > $@
diff --git a/gst/quicktime/atoms.c b/gst/quicktime/atoms.c
new file mode 100644
index 000000000..5aebd6b69
--- /dev/null
+++ b/gst/quicktime/atoms.c
@@ -0,0 +1,4423 @@
+/* Quicktime muxer plugin for GStreamer
+ * Copyright (C) 2008-2010 Thiago 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>
+
+#include <gst/gst.h>
+#include <gst/base/gstbytewriter.h>
+#include <gst/tag/tag.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 (void)
+{
+ 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 guint32
+atom_full_get_flags_as_uint (AtomFull * full)
+{
+ return full->flags[0] << 16 | full->flags[1] << 8 | full->flags[2];
+}
+
+static void
+atom_full_set_flags_as_uint (AtomFull * full, guint32 flags_as_uint)
+{
+ full->flags[2] = flags_as_uint & 0xFF;
+ full->flags[1] = (flags_as_uint & 0xFF00) >> 8;
+ full->flags[0] = (flags_as_uint & 0xFF0000) >> 16;
+}
+
+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, copy_func, 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 AtomUUID *
+atom_uuid_new (void)
+{
+ AtomUUID *uuid = g_new0 (AtomUUID, 1);
+
+ atom_header_set (&uuid->header, FOURCC_uuid, 0, 0);
+ return uuid;
+}
+
+static void
+atom_uuid_free (AtomUUID * 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 (void)
+{
+ 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 (void)
+{
+ 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 (void)
+{
+ 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_elst_init (AtomELST * elst)
+{
+ guint8 flags[3] = { 0, 0, 0 };
+ atom_full_init (&elst->header, FOURCC_elst, 0, 0, 0, flags);
+ elst->entries = 0;
+}
+
+static void
+atom_elst_clear (AtomELST * elst)
+{
+ GSList *walker;
+
+ atom_full_clear (&elst->header);
+ walker = elst->entries;
+ while (walker) {
+ g_free ((EditListEntry *) walker->data);
+ walker = g_slist_next (walker);
+ }
+ g_slist_free (elst->entries);
+}
+
+static void
+atom_edts_init (AtomEDTS * edts)
+{
+ atom_header_set (&edts->header, FOURCC_edts, 0, 0);
+ atom_elst_init (&edts->elst);
+}
+
+static void
+atom_edts_clear (AtomEDTS * edts)
+{
+ atom_clear (&edts->header);
+ atom_elst_clear (&edts->elst);
+}
+
+static AtomEDTS *
+atom_edts_new (void)
+{
+ AtomEDTS *edts = g_new0 (AtomEDTS, 1);
+ atom_edts_init (edts);
+ return edts;
+}
+
+static void
+atom_edts_free (AtomEDTS * edts)
+{
+ atom_edts_clear (edts);
+ g_free (edts);
+}
+
+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 (void)
+{
+ 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;
+ stsd->n_entries = 0;
+}
+
+static void
+atom_stsd_remove_entries (AtomSTSD * stsd)
+{
+ GList *walker;
+
+ 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);
+ }
+ stsd->n_entries = 0;
+}
+
+static void
+atom_stsd_clear (AtomSTSD * stsd)
+{
+ atom_stsd_remove_entries (stsd);
+ atom_full_clear (&stsd->header);
+}
+
+static void
+atom_ctts_init (AtomCTTS * ctts)
+{
+ guint8 flags[3] = { 0, 0, 0 };
+
+ atom_full_init (&ctts->header, FOURCC_ctts, 0, 0, 0, flags);
+ atom_array_init (&ctts->entries, 128);
+ ctts->do_pts = FALSE;
+}
+
+static AtomCTTS *
+atom_ctts_new (void)
+{
+ AtomCTTS *ctts = g_new0 (AtomCTTS, 1);
+
+ atom_ctts_init (ctts);
+ return ctts;
+}
+
+static void
+atom_ctts_free (AtomCTTS * ctts)
+{
+ atom_full_clear (&ctts->header);
+ atom_array_clear (&ctts->entries);
+ 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);
+ atom_array_init (&stts->entries, 512);
+}
+
+static void
+atom_stts_clear (AtomSTTS * stts)
+{
+ atom_full_clear (&stts->header);
+ atom_array_clear (&stts->entries);
+}
+
+static void
+atom_stsz_init (AtomSTSZ * stsz)
+{
+ guint8 flags[3] = { 0, 0, 0 };
+
+ atom_full_init (&stsz->header, FOURCC_stsz, 0, 0, 0, flags);
+ atom_array_init (&stsz->entries, 1024);
+ stsz->sample_size = 0;
+ stsz->table_size = 0;
+}
+
+static void
+atom_stsz_clear (AtomSTSZ * stsz)
+{
+ atom_full_clear (&stsz->header);
+ atom_array_clear (&stsz->entries);
+ 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);
+ atom_array_init (&stsc->entries, 128);
+}
+
+static void
+atom_stsc_clear (AtomSTSC * stsc)
+{
+ atom_full_clear (&stsc->header);
+ atom_array_clear (&stsc->entries);
+}
+
+static void
+atom_co64_init (AtomSTCO64 * co64)
+{
+ guint8 flags[3] = { 0, 0, 0 };
+
+ atom_full_init (&co64->header, FOURCC_stco, 0, 0, 0, flags);
+ atom_array_init (&co64->entries, 256);
+}
+
+static void
+atom_stco64_clear (AtomSTCO64 * stco64)
+{
+ atom_full_clear (&stco64->header);
+ atom_array_clear (&stco64->entries);
+}
+
+static void
+atom_stss_init (AtomSTSS * stss)
+{
+ guint8 flags[3] = { 0, 0, 0 };
+
+ atom_full_init (&stss->header, FOURCC_stss, 0, 0, 0, flags);
+ atom_array_init (&stss->entries, 128);
+}
+
+static void
+atom_stss_clear (AtomSTSS * stss)
+{
+ atom_full_clear (&stss->header);
+ atom_array_clear (&stss->entries);
+}
+
+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);
+}
+
+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 (void)
+{
+ 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 (void)
+{
+ 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 (void)
+{
+ AtomURL *url = g_new0 (AtomURL, 1);
+
+ atom_url_init (url);
+ return url;
+}
+
+static AtomFull *
+atom_alis_new (void)
+{
+ 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);
+ trak->edts = NULL;
+ 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_clear (AtomTRAK * trak)
+{
+ atom_clear (&trak->header);
+ atom_tkhd_clear (&trak->tkhd);
+ if (trak->edts)
+ atom_edts_free (trak->edts);
+ atom_mdia_clear (&trak->mdia);
+}
+
+static void
+atom_trak_free (AtomTRAK * trak)
+{
+ atom_trak_clear (trak);
+ 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 (void)
+{
+ 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 (void)
+{
+ 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 (void)
+{
+ 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);
+ atom_full_set_flags_as_uint (&tag->data.header, flags_as_uint);
+ 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_mehd_init (AtomMEHD * mehd)
+{
+ guint8 flags[3] = { 0, 0, 0 };
+
+ atom_full_init (&mehd->header, FOURCC_mehd, 0, 0, 1, flags);
+ mehd->fragment_duration = 0;
+}
+
+static void
+atom_mvex_init (AtomMVEX * mvex)
+{
+ atom_header_set (&mvex->header, FOURCC_mvex, 0, 0);
+ atom_mehd_init (&mvex->mehd);
+ mvex->trexs = NULL;
+}
+
+static void
+atom_moov_init (AtomMOOV * moov, AtomsContext * context)
+{
+ atom_header_set (&(moov->header), FOURCC_moov, 0, 0);
+ atom_mvhd_init (&(moov->mvhd));
+ atom_mvex_init (&(moov->mvex));
+ 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;
+}
+
+static void
+atom_trex_free (AtomTREX * trex)
+{
+ atom_full_clear (&trex->header);
+ g_free (trex);
+}
+
+static void
+atom_mvex_clear (AtomMVEX * mvex)
+{
+ GList *walker;
+
+ atom_clear (&mvex->header);
+ walker = mvex->trexs;
+ while (walker) {
+ atom_trex_free ((AtomTREX *) walker->data);
+ walker = g_list_next (walker);
+ }
+ g_list_free (mvex->trexs);
+ mvex->trexs = NULL;
+}
+
+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;
+ }
+
+ atom_mvex_clear (&moov->mvex);
+
+ 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;
+}
+
+static guint64
+atom_uuid_copy_data (AtomUUID * uuid, guint8 ** buffer, guint64 * size,
+ guint64 * offset)
+{
+ guint64 original_offset = *offset;
+
+ if (!atom_copy_data (&uuid->header, buffer, size, offset)) {
+ return 0;
+ }
+ prop_copy_uint8_array (uuid->uuid, 16, buffer, size, offset);
+ if (uuid->datalen)
+ prop_copy_uint8_array (uuid->data, uuid->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;
+}
+
+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_size_string ((guint8 *) hdlr->name, strlen (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;
+}
+
+guint64
+atom_stts_copy_data (AtomSTTS * stts, guint8 ** buffer, guint64 * size,
+ guint64 * offset)
+{
+ guint64 original_offset = *offset;
+ guint i;
+
+ if (!atom_full_copy_data (&stts->header, buffer, size, offset)) {
+ return 0;
+ }
+
+ prop_copy_uint32 (atom_array_get_len (&stts->entries), buffer, size, offset);
+ /* minimize realloc */
+ prop_copy_ensure_buffer (buffer, size, offset,
+ 8 * atom_array_get_len (&stts->entries));
+ for (i = 0; i < atom_array_get_len (&stts->entries); i++) {
+ STTSEntry *entry = &atom_array_index (&stts->entries, i);
+
+ 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;
+}
+
+guint64
+atom_stsz_copy_data (AtomSTSZ * stsz, guint8 ** buffer, guint64 * size,
+ guint64 * offset)
+{
+ guint64 original_offset = *offset;
+ guint i;
+
+ 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);
+ if (stsz->sample_size == 0) {
+ /* minimize realloc */
+ prop_copy_ensure_buffer (buffer, size, offset, 4 * stsz->table_size);
+ /* entry count must match sample count */
+ g_assert (atom_array_get_len (&stsz->entries) == stsz->table_size);
+ for (i = 0; i < atom_array_get_len (&stsz->entries); i++) {
+ prop_copy_uint32 (atom_array_index (&stsz->entries, i), buffer, size,
+ offset);
+ }
+ }
+
+ atom_write_size (buffer, size, offset, original_offset);
+ return *offset - original_offset;
+}
+
+guint64
+atom_stsc_copy_data (AtomSTSC * stsc, guint8 ** buffer, guint64 * size,
+ guint64 * offset)
+{
+ guint64 original_offset = *offset;
+ guint i;
+
+ if (!atom_full_copy_data (&stsc->header, buffer, size, offset)) {
+ return 0;
+ }
+
+ prop_copy_uint32 (atom_array_get_len (&stsc->entries), buffer, size, offset);
+ /* minimize realloc */
+ prop_copy_ensure_buffer (buffer, size, offset,
+ 12 * atom_array_get_len (&stsc->entries));
+
+ for (i = 0; i < atom_array_get_len (&stsc->entries); i++) {
+ STSCEntry *entry = &atom_array_index (&stsc->entries, i);
+
+ 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;
+}
+
+guint64
+atom_ctts_copy_data (AtomCTTS * ctts, guint8 ** buffer, guint64 * size,
+ guint64 * offset)
+{
+ guint64 original_offset = *offset;
+ guint i;
+
+ if (!atom_full_copy_data (&ctts->header, buffer, size, offset)) {
+ return 0;
+ }
+
+ prop_copy_uint32 (atom_array_get_len (&ctts->entries), buffer, size, offset);
+ /* minimize realloc */
+ prop_copy_ensure_buffer (buffer, size, offset,
+ 8 * atom_array_get_len (&ctts->entries));
+ for (i = 0; i < atom_array_get_len (&ctts->entries); i++) {
+ CTTSEntry *entry = &atom_array_index (&ctts->entries, i);
+
+ 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;
+}
+
+guint64
+atom_stco64_copy_data (AtomSTCO64 * stco64, guint8 ** buffer, guint64 * size,
+ guint64 * offset)
+{
+ guint64 original_offset = *offset;
+ guint i;
+ 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 (atom_array_get_len (&stco64->entries), buffer, size,
+ offset);
+
+ /* minimize realloc */
+ prop_copy_ensure_buffer (buffer, size, offset,
+ 8 * atom_array_get_len (&stco64->entries));
+ for (i = 0; i < atom_array_get_len (&stco64->entries); i++) {
+ guint64 *value = &atom_array_index (&stco64->entries, i);
+
+ 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;
+}
+
+guint64
+atom_stss_copy_data (AtomSTSS * stss, guint8 ** buffer, guint64 * size,
+ guint64 * offset)
+{
+ guint64 original_offset = *offset;
+ guint i;
+
+ if (atom_array_get_len (&stss->entries) == 0) {
+ /* 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 (atom_array_get_len (&stss->entries), buffer, size, offset);
+ /* minimize realloc */
+ prop_copy_ensure_buffer (buffer, size, offset,
+ 4 * atom_array_get_len (&stss->entries));
+ for (i = 0; i < atom_array_get_len (&stss->entries); i++) {
+ prop_copy_uint32 (atom_array_index (&stss->entries, i), 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) {
+ if (!sample_entry_mp4v_copy_data ((SampleTableEntryMP4V *)
+ walker->data, buffer, size, offset)) {
+ return 0;
+ }
+ } else if (se->kind == AUDIO) {
+ if (!sample_entry_mp4a_copy_data ((SampleTableEntryMP4A *)
+ walker->data, buffer, size, offset)) {
+ return 0;
+ }
+ } 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 (atom_array_get_len (&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 && stbl->ctts->do_pts) {
+ 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_elst_copy_data (AtomELST * elst, guint8 ** buffer, guint64 * size,
+ guint64 * offset)
+{
+ guint64 original_offset = *offset;
+ GSList *walker;
+
+ if (!atom_full_copy_data (&elst->header, buffer, size, offset)) {
+ return 0;
+ }
+
+ prop_copy_uint32 (g_slist_length (elst->entries), buffer, size, offset);
+
+ for (walker = elst->entries; walker != NULL; walker = g_slist_next (walker)) {
+ EditListEntry *entry = (EditListEntry *) walker->data;
+ prop_copy_uint32 (entry->duration, buffer, size, offset);
+ prop_copy_uint32 (entry->media_time, buffer, size, offset);
+ prop_copy_uint32 (entry->media_rate, buffer, size, offset);
+ }
+ atom_write_size (buffer, size, offset, original_offset);
+ return *offset - original_offset;
+}
+
+static guint64
+atom_edts_copy_data (AtomEDTS * edts, guint8 ** buffer, guint64 * size,
+ guint64 * offset)
+{
+ guint64 original_offset = *offset;
+
+ if (!atom_copy_data (&(edts->header), buffer, size, offset))
+ return 0;
+
+ if (!atom_elst_copy_data (&(edts->elst), buffer, size, offset))
+ return 0;
+
+ atom_write_size (buffer, size, offset, original_offset);
+ return *offset - original_offset;
+}
+
+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 (trak->edts) {
+ if (!atom_edts_copy_data (trak->edts, 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;
+ }
+ }
+ 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;
+}
+
+static guint64
+atom_mehd_copy_data (AtomMEHD * mehd, guint8 ** buffer, guint64 * size,
+ guint64 * offset)
+{
+ guint64 original_offset = *offset;
+
+ if (!atom_full_copy_data (&mehd->header, buffer, size, offset)) {
+ return 0;
+ }
+
+ prop_copy_uint64 (mehd->fragment_duration, buffer, size, offset);
+
+ atom_write_size (buffer, size, offset, original_offset);
+ return *offset - original_offset;
+}
+
+static guint64
+atom_trex_copy_data (AtomTREX * trex, guint8 ** buffer, guint64 * size,
+ guint64 * offset)
+{
+ guint64 original_offset = *offset;
+
+ if (!atom_full_copy_data (&trex->header, buffer, size, offset)) {
+ return 0;
+ }
+
+ prop_copy_uint32 (trex->track_ID, buffer, size, offset);
+ prop_copy_uint32 (trex->default_sample_description_index, buffer, size,
+ offset);
+ prop_copy_uint32 (trex->default_sample_duration, buffer, size, offset);
+ prop_copy_uint32 (trex->default_sample_size, buffer, size, offset);
+ prop_copy_uint32 (trex->default_sample_flags, buffer, size, offset);
+
+ atom_write_size (buffer, size, offset, original_offset);
+ return *offset - original_offset;
+}
+
+static guint64
+atom_mvex_copy_data (AtomMVEX * mvex, guint8 ** buffer, guint64 * size,
+ guint64 * offset)
+{
+ guint64 original_offset = *offset;
+ GList *walker;
+
+ if (!atom_copy_data (&mvex->header, buffer, size, offset)) {
+ return 0;
+ }
+
+ if (!atom_mehd_copy_data (&mvex->mehd, buffer, size, offset)) {
+ return 0;
+ }
+
+ walker = g_list_first (mvex->trexs);
+ while (walker != NULL) {
+ if (!atom_trex_copy_data ((AtomTREX *) walker->data, buffer, size, offset)) {
+ return 0;
+ }
+ walker = g_list_next (walker);
+ }
+
+ 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;
+ }
+ }
+
+ if (atom->fragmented) {
+ if (!atom_mvex_copy_data (&atom->mvex, 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 void
+atom_stsc_add_new_entry (AtomSTSC * stsc, guint32 first_chunk, guint32 nsamples)
+{
+ STSCEntry nentry;
+ gint len;
+
+ if ((len = atom_array_get_len (&stsc->entries)) &&
+ ((atom_array_index (&stsc->entries, len - 1)).samples_per_chunk ==
+ nsamples))
+ return;
+
+ nentry.first_chunk = first_chunk;
+ nentry.samples_per_chunk = nsamples;
+ nentry.sample_description_index = 1;
+ atom_array_append (&stsc->entries, nentry, 128);
+}
+
+static void
+atom_stts_add_entry (AtomSTTS * stts, guint32 sample_count, gint32 sample_delta)
+{
+ STTSEntry *entry = NULL;
+
+ if (G_LIKELY (atom_array_get_len (&stts->entries) != 0))
+ entry = &atom_array_index (&stts->entries,
+ atom_array_get_len (&stts->entries) - 1);
+
+ if (entry && entry->sample_delta == sample_delta) {
+ entry->sample_count += sample_count;
+ } else {
+ STTSEntry nentry;
+
+ nentry.sample_count = sample_count;
+ nentry.sample_delta = sample_delta;
+ atom_array_append (&stts->entries, nentry, 256);
+ }
+}
+
+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++) {
+ atom_array_append (&stsz->entries, size, 1024);
+ }
+}
+
+static guint32
+atom_stco64_get_entry_count (AtomSTCO64 * stco64)
+{
+ return atom_array_get_len (&stco64->entries);
+}
+
+static void
+atom_stco64_add_entry (AtomSTCO64 * stco64, guint64 entry)
+{
+ atom_array_append (&stco64->entries, entry, 256);
+ if (entry > G_MAXUINT32)
+ stco64->header.header.type = FOURCC_co64;
+}
+
+static void
+atom_stss_add_entry (AtomSTSS * stss, guint32 sample)
+{
+ atom_array_append (&stss->entries, sample, 512);
+}
+
+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)
+{
+ CTTSEntry *entry = NULL;
+
+ if (G_LIKELY (atom_array_get_len (&ctts->entries) != 0))
+ entry = &atom_array_index (&ctts->entries,
+ atom_array_get_len (&ctts->entries) - 1);
+
+ if (entry == NULL || entry->sampleoffset != offset) {
+ CTTSEntry nentry;
+
+ nentry.samplecount = nsamples;
+ nentry.sampleoffset = offset;
+ atom_array_append (&ctts->entries, nentry, 256);
+ if (offset != 0)
+ ctts->do_pts = TRUE;
+ } 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_stbl_add_samples (AtomSTBL * stbl, guint32 nsamples, guint32 delta,
+ guint32 size, guint64 chunk_offset, gboolean sync, gint64 pts_offset)
+{
+ 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);
+ /* always store to arrange for consistent content */
+ atom_stbl_add_ctts_entry (stbl, nsamples, pts_offset);
+}
+
+void
+atom_trak_add_samples (AtomTRAK * trak, guint32 nsamples, guint32 delta,
+ guint32 size, guint64 chunk_offset, gboolean sync, gint64 pts_offset)
+{
+ AtomSTBL *stbl = &trak->mdia.minf.stbl;
+ atom_stbl_add_samples (stbl, nsamples, delta, size, chunk_offset, sync,
+ pts_offset);
+}
+
+/* trak and moov molding */
+
+guint32
+atom_trak_get_timescale (AtomTRAK * trak)
+{
+ return trak->mdia.mdhd.time_info.timescale;
+}
+
+guint32
+atom_trak_get_id (AtomTRAK * trak)
+{
+ return trak->tkhd.track_ID;
+}
+
+static void
+atom_trak_set_id (AtomTRAK * trak, guint32 id)
+{
+ trak->tkhd.track_ID = id;
+}
+
+static void
+atom_moov_add_trex (AtomMOOV * moov, AtomTREX * trex)
+{
+ moov->mvex.trexs = g_list_append (moov->mvex.trexs, trex);
+}
+
+static AtomTREX *
+atom_trex_new (AtomTRAK * trak)
+{
+ guint8 flags[3] = { 0, 0, 0 };
+ AtomTREX *trex = g_new0 (AtomTREX, 1);
+
+ atom_full_init (&trex->header, FOURCC_trex, 0, 0, 0, flags);
+
+ trex->track_ID = trak->tkhd.track_ID;
+ trex->default_sample_description_index = 1;
+ trex->default_sample_duration = 0;
+ trex->default_sample_size = 0;
+ trex->default_sample_flags = 0;
+
+ return trex;
+}
+
+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);
+ /* additional trak means also new trex */
+ atom_moov_add_trex (moov, atom_trex_new (trak));
+}
+
+static guint64
+atom_trak_get_duration (AtomTRAK * trak)
+{
+ return trak->tkhd.duration;
+}
+
+static guint64
+atom_stts_get_total_duration (AtomSTTS * stts)
+{
+ guint i;
+ guint64 sum = 0;
+
+ for (i = 0; i < atom_array_get_len (&stts->entries); i++) {
+ STTSEntry *entry = &atom_array_index (&stts->entries, i);
+
+ sum += (guint64) (entry->sample_count) * entry->sample_delta;
+ }
+ 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;
+ moov->mvex.mehd.fragment_duration = duration;
+}
+
+void
+atom_moov_set_fragmented (AtomMOOV * moov, gboolean fragmented)
+{
+ moov->fragmented = fragmented;
+}
+
+void
+atom_stco64_chunks_add_offset (AtomSTCO64 * stco64, guint32 offset)
+{
+ guint i;
+
+ for (i = 0; i < atom_array_get_len (&stco64->entries); i++) {
+ guint64 *value = &atom_array_index (&stco64->entries, i);
+
+ *value += offset;
+ }
+}
+
+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, atom_tag_copy_data,
+ 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, atom_data_copy_data,
+ 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, atom_data_copy_data,
+ 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);
+}
+
+void
+atom_moov_add_xmp_tags (AtomMOOV * moov, GstBuffer * xmpbuffer)
+{
+ AtomData *data_atom = NULL;
+
+ if (moov->context.flavor == ATOMS_TREE_FLAVOR_MOV) {
+ if (xmpbuffer) {
+ data_atom = atom_data_new_from_gst_buffer (FOURCC_XMP_, xmpbuffer);
+ atom_moov_init_metatags (moov, &moov->context);
+ moov->udta->entries = g_list_append (moov->udta->entries,
+ build_atom_info_wrapper ((Atom *) data_atom, atom_data_copy_data,
+ atom_data_free));
+ }
+ } else {
+ GST_DEBUG ("Not adding xmp to moov atom, it is only used in 'mov' format");
+ }
+
+}
+
+/*
+ * 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_hdlr_set_name (AtomHDLR * hdlr, const char *name)
+{
+ if (hdlr->name)
+ g_free (hdlr->name);
+ hdlr->name = g_strdup (name);
+}
+
+static void
+atom_mdia_set_hdlr_type_audio (AtomMDIA * mdia, AtomsContext * context)
+{
+ atom_hdlr_set_type (&mdia->hdlr, context, FOURCC_mhlr, FOURCC_soun);
+ /* Some players (low-end hardware) check for this name, which is what
+ * QuickTime itself sets */
+ atom_hdlr_set_name (&mdia->hdlr, "SoundHandler");
+}
+
+static void
+atom_mdia_set_hdlr_type_video (AtomMDIA * mdia, AtomsContext * context)
+{
+ atom_hdlr_set_type (&mdia->hdlr, context, FOURCC_mhlr, FOURCC_vide);
+ /* Some players (low-end hardware) check for this name, which is what
+ * QuickTime itself sets */
+ atom_hdlr_set_name (&mdia->hdlr, "VideoHandler");
+}
+
+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;
+}
+
+static void
+atom_edts_add_entry (AtomEDTS * edts, EditListEntry * entry)
+{
+ edts->elst.entries = g_slist_append (edts->elst.entries, entry);
+}
+
+/*
+ * Adds a new entry to this trak edits list
+ * duration is in the moov's timescale
+ * media_time is the offset in the media time to start from (media's timescale)
+ * rate is a 32 bits fixed-point
+ */
+void
+atom_trak_add_elst_entry (AtomTRAK * trak, guint32 duration, guint32 media_time,
+ guint32 rate)
+{
+ EditListEntry *entry = g_new (EditListEntry, 1);
+
+ entry->duration = duration;
+ entry->media_time = media_time;
+ entry->media_rate = rate;
+
+ if (trak->edts == NULL) {
+ trak->edts = atom_edts_new ();
+ }
+ atom_edts_add_entry (trak->edts, entry);
+}
+
+/* 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);
+ atom_stsd_remove_entries (&trak->mdia.minf.stbl.stsd);
+ 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);
+}
+
+static 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, atom_data_copy_data,
+ atom_data_free);
+}
+
+void
+atom_trak_set_video_type (AtomTRAK * trak, AtomsContext * context,
+ VisualSampleEntry * entry, guint32 scale, GList * ext_atoms_list)
+{
+ 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);
+ atom_stsd_remove_entries (&trak->mdia.minf.stbl.stsd);
+ ste = atom_trak_add_video_entry (trak, context, entry->fourcc);
+
+ trak->is_video = TRUE;
+ trak->is_h264 = (entry->fourcc == FOURCC_avc1);
+
+ ste->version = entry->version;
+ 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_atoms_list)
+ ste->extension_atoms = g_list_concat (ste->extension_atoms, ext_atoms_list);
+
+ /* 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));
+ }
+}
+
+static void
+atom_mfhd_init (AtomMFHD * mfhd, guint32 sequence_number)
+{
+ guint8 flags[3] = { 0, 0, 0 };
+
+ atom_full_init (&(mfhd->header), FOURCC_mfhd, 0, 0, 0, flags);
+ mfhd->sequence_number = sequence_number;
+}
+
+static void
+atom_moof_init (AtomMOOF * moof, AtomsContext * context,
+ guint32 sequence_number)
+{
+ atom_header_set (&moof->header, FOURCC_moof, 0, 0);
+ atom_mfhd_init (&moof->mfhd, sequence_number);
+ moof->trafs = NULL;
+}
+
+AtomMOOF *
+atom_moof_new (AtomsContext * context, guint32 sequence_number)
+{
+ AtomMOOF *moof = g_new0 (AtomMOOF, 1);
+
+ atom_moof_init (moof, context, sequence_number);
+ return moof;
+}
+
+static void
+atom_trun_free (AtomTRUN * trun)
+{
+ atom_full_clear (&trun->header);
+ atom_array_clear (&trun->entries);
+ g_free (trun);
+}
+
+static void
+atom_sdtp_free (AtomSDTP * sdtp)
+{
+ atom_full_clear (&sdtp->header);
+ atom_array_clear (&sdtp->entries);
+ g_free (sdtp);
+}
+
+void
+atom_traf_free (AtomTRAF * traf)
+{
+ GList *walker;
+
+ walker = traf->truns;
+ while (walker) {
+ atom_trun_free ((AtomTRUN *) walker->data);
+ walker = g_list_next (walker);
+ }
+ g_list_free (traf->truns);
+ traf->truns = NULL;
+
+ walker = traf->sdtps;
+ while (walker) {
+ atom_sdtp_free ((AtomSDTP *) walker->data);
+ walker = g_list_next (walker);
+ }
+ g_list_free (traf->sdtps);
+ traf->sdtps = NULL;
+
+ g_free (traf);
+}
+
+void
+atom_moof_free (AtomMOOF * moof)
+{
+ GList *walker;
+
+ walker = moof->trafs;
+ while (walker) {
+ atom_traf_free ((AtomTRAF *) walker->data);
+ walker = g_list_next (walker);
+ }
+ g_list_free (moof->trafs);
+ moof->trafs = NULL;
+
+ g_free (moof);
+}
+
+static guint64
+atom_mfhd_copy_data (AtomMFHD * mfhd, guint8 ** buffer, guint64 * size,
+ guint64 * offset)
+{
+ guint64 original_offset = *offset;
+
+ if (!atom_full_copy_data (&mfhd->header, buffer, size, offset)) {
+ return 0;
+ }
+
+ prop_copy_uint32 (mfhd->sequence_number, buffer, size, offset);
+
+ atom_write_size (buffer, size, offset, original_offset);
+ return *offset - original_offset;
+}
+
+static guint64
+atom_tfhd_copy_data (AtomTFHD * tfhd, guint8 ** buffer, guint64 * size,
+ guint64 * offset)
+{
+ guint64 original_offset = *offset;
+ guint32 flags;
+
+ if (!atom_full_copy_data (&tfhd->header, buffer, size, offset)) {
+ return 0;
+ }
+
+ prop_copy_uint32 (tfhd->track_ID, buffer, size, offset);
+
+ flags = atom_full_get_flags_as_uint (&tfhd->header);
+
+ if (flags & TF_BASE_DATA_OFFSET)
+ prop_copy_uint64 (tfhd->base_data_offset, buffer, size, offset);
+ if (flags & TF_SAMPLE_DESCRIPTION_INDEX)
+ prop_copy_uint32 (tfhd->sample_description_index, buffer, size, offset);
+ if (flags & TF_DEFAULT_SAMPLE_DURATION)
+ prop_copy_uint32 (tfhd->default_sample_duration, buffer, size, offset);
+ if (flags & TF_DEFAULT_SAMPLE_SIZE)
+ prop_copy_uint32 (tfhd->default_sample_size, buffer, size, offset);
+ if (flags & TF_DEFAULT_SAMPLE_FLAGS)
+ prop_copy_uint32 (tfhd->default_sample_flags, buffer, size, offset);
+
+ atom_write_size (buffer, size, offset, original_offset);
+ return *offset - original_offset;
+}
+
+static guint64
+atom_trun_copy_data (AtomTRUN * trun, guint8 ** buffer, guint64 * size,
+ guint64 * offset, guint32 * data_offset)
+{
+ guint64 original_offset = *offset;
+ guint32 flags, i;
+
+ flags = atom_full_get_flags_as_uint (&trun->header);
+
+ /* if first trun in moof, forcibly add data_offset and record
+ * where it must be written later on */
+ if (data_offset && !*data_offset) {
+ flags |= TR_DATA_OFFSET;
+ } else {
+ flags &= ~TR_DATA_OFFSET;
+ }
+
+ atom_full_set_flags_as_uint (&trun->header, flags);
+
+ if (!atom_full_copy_data (&trun->header, buffer, size, offset)) {
+ return 0;
+ }
+
+ prop_copy_uint32 (trun->sample_count, buffer, size, offset);
+
+ if (flags & TR_DATA_OFFSET) {
+ *data_offset = *offset;
+ prop_copy_int32 (trun->data_offset, buffer, size, offset);
+ }
+ if (flags & TR_FIRST_SAMPLE_FLAGS)
+ prop_copy_uint32 (trun->first_sample_flags, buffer, size, offset);
+
+ for (i = 0; i < atom_array_get_len (&trun->entries); i++) {
+ TRUNSampleEntry *entry = &atom_array_index (&trun->entries, i);
+
+ if (flags & TR_SAMPLE_DURATION)
+ prop_copy_uint32 (entry->sample_duration, buffer, size, offset);
+ if (flags & TR_SAMPLE_SIZE)
+ prop_copy_uint32 (entry->sample_size, buffer, size, offset);
+ if (flags & TR_SAMPLE_FLAGS)
+ prop_copy_uint32 (entry->sample_flags, buffer, size, offset);
+ if (flags & TR_COMPOSITION_TIME_OFFSETS)
+ prop_copy_uint32 (entry->sample_composition_time_offset,
+ buffer, size, offset);
+ }
+
+ atom_write_size (buffer, size, offset, original_offset);
+ return *offset - original_offset;
+}
+
+static guint64
+atom_sdtp_copy_data (AtomSDTP * sdtp, guint8 ** buffer, guint64 * size,
+ guint64 * offset)
+{
+ guint64 original_offset = *offset;
+
+ if (!atom_full_copy_data (&sdtp->header, buffer, size, offset)) {
+ return 0;
+ }
+
+ /* all entries at once */
+ prop_copy_fixed_size_string (&atom_array_index (&sdtp->entries, 0),
+ atom_array_get_len (&sdtp->entries), buffer, size, offset);
+
+ atom_write_size (buffer, size, offset, original_offset);
+ return *offset - original_offset;
+}
+
+static guint64
+atom_traf_copy_data (AtomTRAF * traf, guint8 ** buffer, guint64 * size,
+ guint64 * offset, guint32 * data_offset)
+{
+ guint64 original_offset = *offset;
+ GList *walker;
+
+ if (!atom_copy_data (&traf->header, buffer, size, offset)) {
+ return 0;
+ }
+ if (!atom_tfhd_copy_data (&traf->tfhd, buffer, size, offset)) {
+ return 0;
+ }
+
+ walker = g_list_first (traf->truns);
+ while (walker != NULL) {
+ if (!atom_trun_copy_data ((AtomTRUN *) walker->data, buffer, size, offset,
+ data_offset)) {
+ return 0;
+ }
+ walker = g_list_next (walker);
+ }
+
+ walker = g_list_first (traf->sdtps);
+ while (walker != NULL) {
+ if (!atom_sdtp_copy_data ((AtomSDTP *) walker->data, buffer, size, offset)) {
+ return 0;
+ }
+ walker = g_list_next (walker);
+ }
+
+ atom_write_size (buffer, size, offset, original_offset);
+ return *offset - original_offset;
+}
+
+/* creates moof atom; metadata is written expecting actual buffer data
+ * is in mdata directly after moof, and is consecutively written per trak */
+guint64
+atom_moof_copy_data (AtomMOOF * moof, guint8 ** buffer,
+ guint64 * size, guint64 * offset)
+{
+ guint64 original_offset = *offset;
+ GList *walker;
+ guint32 data_offset = 0;
+
+ if (!atom_copy_data (&moof->header, buffer, size, offset))
+ return 0;
+
+ if (!atom_mfhd_copy_data (&moof->mfhd, buffer, size, offset))
+ return 0;
+
+ walker = g_list_first (moof->trafs);
+ while (walker != NULL) {
+ if (!atom_traf_copy_data ((AtomTRAF *) walker->data, buffer, size, offset,
+ &data_offset)) {
+ return 0;
+ }
+ walker = g_list_next (walker);
+ }
+
+ atom_write_size (buffer, size, offset, original_offset);
+
+ if (*buffer && data_offset) {
+ /* first trun needs a data-offset relative to moof start
+ * = moof size + mdat prefix */
+ GST_WRITE_UINT32_BE (*buffer + data_offset, *offset - original_offset + 8);
+ }
+
+ return *offset - original_offset;
+}
+
+static void
+atom_tfhd_init (AtomTFHD * tfhd, guint32 track_ID)
+{
+ guint8 flags[3] = { 0, 0, 0 };
+
+ atom_full_init (&tfhd->header, FOURCC_tfhd, 0, 0, 0, flags);
+ tfhd->track_ID = track_ID;
+ tfhd->base_data_offset = 0;
+ tfhd->sample_description_index = 1;
+ tfhd->default_sample_duration = 0;
+ tfhd->default_sample_size = 0;
+ tfhd->default_sample_flags = 0;
+}
+
+static void
+atom_trun_init (AtomTRUN * trun)
+{
+ guint8 flags[3] = { 0, 0, 0 };
+
+ atom_full_init (&trun->header, FOURCC_trun, 0, 0, 0, flags);
+ trun->sample_count = 0;
+ trun->data_offset = 0;
+ trun->first_sample_flags = 0;
+ atom_array_init (&trun->entries, 512);
+}
+
+static AtomTRUN *
+atom_trun_new (void)
+{
+ AtomTRUN *trun = g_new0 (AtomTRUN, 1);
+
+ atom_trun_init (trun);
+ return trun;
+}
+
+static void
+atom_sdtp_init (AtomSDTP * sdtp)
+{
+ guint8 flags[3] = { 0, 0, 0 };
+
+ atom_full_init (&sdtp->header, FOURCC_sdtp, 0, 0, 0, flags);
+ atom_array_init (&sdtp->entries, 512);
+}
+
+static AtomSDTP *
+atom_sdtp_new (AtomsContext * context)
+{
+ AtomSDTP *sdtp = g_new0 (AtomSDTP, 1);
+
+ atom_sdtp_init (sdtp);
+ return sdtp;
+}
+
+static void
+atom_traf_add_sdtp (AtomTRAF * traf, AtomSDTP * sdtp)
+{
+ traf->sdtps = g_list_append (traf->sdtps, sdtp);
+}
+
+static void
+atom_sdtp_add_samples (AtomSDTP * sdtp, guint8 val)
+{
+ /* it does not make much/any sense according to specs,
+ * but that's how MS isml samples seem to do it */
+ atom_array_append (&sdtp->entries, val, 256);
+}
+
+static void
+atom_trun_add_samples (AtomTRUN * trun, guint32 delta, guint32 size,
+ guint32 flags, gint64 pts_offset)
+{
+ TRUNSampleEntry nentry;
+
+ if (pts_offset != 0)
+ trun->header.flags[1] |= TR_COMPOSITION_TIME_OFFSETS;
+
+ nentry.sample_duration = delta;
+ nentry.sample_size = size;
+ nentry.sample_flags = flags;
+ nentry.sample_composition_time_offset = pts_offset;
+ atom_array_append (&trun->entries, nentry, 256);
+ trun->sample_count++;
+}
+
+static void
+atom_traf_init (AtomTRAF * traf, AtomsContext * context, guint32 track_ID)
+{
+ atom_header_set (&traf->header, FOURCC_traf, 0, 0);
+ atom_tfhd_init (&traf->tfhd, track_ID);
+ traf->truns = NULL;
+
+ if (context->flavor == ATOMS_TREE_FLAVOR_ISML)
+ atom_traf_add_sdtp (traf, atom_sdtp_new (context));
+}
+
+AtomTRAF *
+atom_traf_new (AtomsContext * context, guint32 track_ID)
+{
+ AtomTRAF *traf = g_new0 (AtomTRAF, 1);
+
+ atom_traf_init (traf, context, track_ID);
+ return traf;
+}
+
+static void
+atom_traf_add_trun (AtomTRAF * traf, AtomTRUN * trun)
+{
+ traf->truns = g_list_append (traf->truns, trun);
+}
+
+void
+atom_traf_add_samples (AtomTRAF * traf, guint32 delta, guint32 size,
+ gboolean sync, gint64 pts_offset, gboolean sdtp_sync)
+{
+ AtomTRUN *trun;
+ guint32 flags;
+
+ /* 0x10000 is sample-is-difference-sample flag
+ * low byte stuff is what ismv uses */
+ flags = (sync ? 0x0 : 0x10000) | (sdtp_sync ? 0x40 : 0xc0);
+
+ if (G_UNLIKELY (!traf->truns)) {
+ trun = atom_trun_new ();
+ atom_traf_add_trun (traf, trun);
+ /* optimistic; indicate all defaults present in tfhd */
+ traf->tfhd.header.flags[2] = TF_DEFAULT_SAMPLE_DURATION |
+ TF_DEFAULT_SAMPLE_SIZE | TF_DEFAULT_SAMPLE_FLAGS;
+ traf->tfhd.default_sample_duration = delta;
+ traf->tfhd.default_sample_size = size;
+ traf->tfhd.default_sample_flags = flags;
+ trun->first_sample_flags = flags;
+ }
+
+ trun = traf->truns->data;
+
+ /* check if still matching defaults,
+ * if not, abandon default and need entry for each sample */
+ if (traf->tfhd.default_sample_duration != delta) {
+ traf->tfhd.header.flags[2] &= ~TF_DEFAULT_SAMPLE_DURATION;
+ trun->header.flags[1] |= (TR_SAMPLE_DURATION >> 8);
+ }
+ if (traf->tfhd.default_sample_size != size) {
+ traf->tfhd.header.flags[2] &= ~TF_DEFAULT_SAMPLE_SIZE;
+ trun->header.flags[1] |= (TR_SAMPLE_SIZE >> 8);
+ }
+ if (traf->tfhd.default_sample_flags != flags) {
+ if (trun->sample_count == 1) {
+ /* at least will need first sample flag */
+ traf->tfhd.default_sample_flags = flags;
+ trun->header.flags[2] |= TR_FIRST_SAMPLE_FLAGS;
+ } else {
+ /* now we need sample flags for each sample */
+ traf->tfhd.header.flags[2] &= ~TF_DEFAULT_SAMPLE_FLAGS;
+ trun->header.flags[1] |= (TR_SAMPLE_FLAGS >> 8);
+ trun->header.flags[2] &= ~TR_FIRST_SAMPLE_FLAGS;
+ }
+ }
+
+ atom_trun_add_samples (traf->truns->data, delta, size, flags, pts_offset);
+
+ if (traf->sdtps)
+ atom_sdtp_add_samples (traf->sdtps->data, 0x10 | ((flags & 0xff) >> 4));
+}
+
+guint32
+atom_traf_get_sample_num (AtomTRAF * traf)
+{
+ AtomTRUN *trun;
+
+ if (G_UNLIKELY (!traf->truns))
+ return 0;
+
+ trun = traf->truns->data;
+ return atom_array_get_len (&trun->entries);
+}
+
+void
+atom_moof_add_traf (AtomMOOF * moof, AtomTRAF * traf)
+{
+ moof->trafs = g_list_append (moof->trafs, traf);
+}
+
+static void
+atom_tfra_free (AtomTFRA * tfra)
+{
+ atom_full_clear (&tfra->header);
+ atom_array_clear (&tfra->entries);
+ g_free (tfra);
+}
+
+AtomMFRA *
+atom_mfra_new (AtomsContext * context)
+{
+ AtomMFRA *mfra = g_new0 (AtomMFRA, 1);
+
+ atom_header_set (&mfra->header, FOURCC_mfra, 0, 0);
+ return mfra;
+}
+
+void
+atom_mfra_add_tfra (AtomMFRA * mfra, AtomTFRA * tfra)
+{
+ mfra->tfras = g_list_append (mfra->tfras, tfra);
+}
+
+void
+atom_mfra_free (AtomMFRA * mfra)
+{
+ GList *walker;
+
+ walker = mfra->tfras;
+ while (walker) {
+ atom_tfra_free ((AtomTFRA *) walker->data);
+ walker = g_list_next (walker);
+ }
+ g_list_free (mfra->tfras);
+ mfra->tfras = NULL;
+
+ atom_clear (&mfra->header);
+ g_free (mfra);
+}
+
+static void
+atom_tfra_init (AtomTFRA * tfra, guint32 track_ID)
+{
+ guint8 flags[3] = { 0, 0, 0 };
+
+ atom_full_init (&tfra->header, FOURCC_tfra, 0, 0, 0, flags);
+ tfra->track_ID = track_ID;
+ atom_array_init (&tfra->entries, 512);
+}
+
+AtomTFRA *
+atom_tfra_new (AtomsContext * context, guint32 track_ID)
+{
+ AtomTFRA *tfra = g_new0 (AtomTFRA, 1);
+
+ atom_tfra_init (tfra, track_ID);
+ return tfra;
+
+}
+
+static inline gint
+need_bytes (guint32 num)
+{
+ gint n = 0;
+
+ while (num >>= 8)
+ n++;
+
+ return n;
+}
+
+void
+atom_tfra_add_entry (AtomTFRA * tfra, guint64 dts, guint32 sample_num)
+{
+ TFRAEntry entry;
+
+ entry.time = dts;
+ /* fill in later */
+ entry.moof_offset = 0;
+ /* always write a single trun in a single traf */
+ entry.traf_number = 1;
+ entry.trun_number = 1;
+ entry.sample_number = sample_num;
+
+ /* auto-use 64 bits if needed */
+ if (dts > G_MAXUINT32)
+ tfra->header.version = 1;
+
+ /* 1 byte will always do for traf and trun number,
+ * check how much sample_num needs */
+ tfra->lengths = (tfra->lengths & 0xfc) ||
+ MAX (tfra->lengths, need_bytes (sample_num));
+
+ atom_array_append (&tfra->entries, entry, 256);
+}
+
+void
+atom_tfra_update_offset (AtomTFRA * tfra, guint64 offset)
+{
+ gint i;
+
+ /* auto-use 64 bits if needed */
+ if (offset > G_MAXUINT32)
+ tfra->header.version = 1;
+
+ for (i = atom_array_get_len (&tfra->entries) - 1; i >= 0; i--) {
+ TFRAEntry *entry = &atom_array_index (&tfra->entries, i);
+
+ if (entry->moof_offset)
+ break;
+ entry->moof_offset = offset;
+ }
+}
+
+static guint64
+atom_tfra_copy_data (AtomTFRA * tfra, guint8 ** buffer, guint64 * size,
+ guint64 * offset)
+{
+ guint64 original_offset = *offset;
+ guint32 i;
+ TFRAEntry *entry;
+ guint32 data;
+ guint bytes;
+ guint version;
+
+ if (!atom_full_copy_data (&tfra->header, buffer, size, offset)) {
+ return 0;
+ }
+
+ prop_copy_uint32 (tfra->track_ID, buffer, size, offset);
+ prop_copy_uint32 (tfra->lengths, buffer, size, offset);
+ prop_copy_uint32 (atom_array_get_len (&tfra->entries), buffer, size, offset);
+
+ version = tfra->header.version;
+ for (i = 0; i < atom_array_get_len (&tfra->entries); ++i) {
+ entry = &atom_array_index (&tfra->entries, i);
+ if (version) {
+ prop_copy_uint64 (entry->time, buffer, size, offset);
+ prop_copy_uint64 (entry->moof_offset, buffer, size, offset);
+ } else {
+ prop_copy_uint32 (entry->time, buffer, size, offset);
+ prop_copy_uint32 (entry->moof_offset, buffer, size, offset);
+ }
+
+ bytes = (tfra->lengths & (0x3 << 4)) + 1;
+ data = GUINT32_TO_BE (entry->traf_number);
+ prop_copy_fixed_size_string (((guint8 *) & data) + 4 - bytes, bytes,
+ buffer, size, offset);
+
+ bytes = (tfra->lengths & (0x3 << 2)) + 1;
+ data = GUINT32_TO_BE (entry->trun_number);
+ prop_copy_fixed_size_string (((guint8 *) & data) + 4 - bytes, bytes,
+ buffer, size, offset);
+
+ bytes = (tfra->lengths & (0x3)) + 1;
+ data = GUINT32_TO_BE (entry->sample_number);
+ prop_copy_fixed_size_string (((guint8 *) & data) + 4 - bytes, bytes,
+ buffer, size, offset);
+
+ }
+
+ atom_write_size (buffer, size, offset, original_offset);
+ return *offset - original_offset;
+}
+
+static guint64
+atom_mfro_copy_data (guint32 s, guint8 ** buffer, guint64 * size,
+ guint64 * offset)
+{
+ guint64 original_offset = *offset;
+ guint8 flags[3] = { 0, 0, 0 };
+ AtomFull mfro;
+
+ atom_full_init (&mfro, FOURCC_mfro, 0, 0, 0, flags);
+
+ if (!atom_full_copy_data (&mfro, buffer, size, offset)) {
+ return 0;
+ }
+
+ prop_copy_uint32 (s, buffer, size, offset);
+
+ atom_write_size (buffer, size, offset, original_offset);
+
+ return *offset - original_offset;
+}
+
+
+guint64
+atom_mfra_copy_data (AtomMFRA * mfra, guint8 ** buffer, guint64 * size,
+ guint64 * offset)
+{
+ guint64 original_offset = *offset;
+ GList *walker;
+
+ if (!atom_copy_data (&mfra->header, buffer, size, offset))
+ return 0;
+
+ walker = g_list_first (mfra->tfras);
+ while (walker != NULL) {
+ if (!atom_tfra_copy_data ((AtomTFRA *) walker->data, buffer, size, offset)) {
+ return 0;
+ }
+ walker = g_list_next (walker);
+ }
+
+ /* 16 is the size of the mfro atom */
+ if (!atom_mfro_copy_data (*offset - original_offset + 16, buffer,
+ size, offset))
+ return 0;
+
+ atom_write_size (buffer, size, offset, original_offset);
+ return *offset - original_offset;
+}
+
+/* some sample description construction helpers */
+
+AtomInfo *
+build_esds_extension (AtomTRAK * trak, guint8 object_type, guint8 stream_type,
+ const GstBuffer * codec_data, guint32 avg_bitrate, guint32 max_bitrate)
+{
+ 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;
+
+ if (avg_bitrate > 0)
+ esds->es.dec_conf_desc.avg_bitrate = avg_bitrate;
+ if (max_bitrate > 0)
+ esds->es.dec_conf_desc.max_bitrate = max_bitrate;
+
+ /* 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, atom_esds_copy_data,
+ atom_esds_free);
+}
+
+AtomInfo *
+build_btrt_extension (guint32 buffer_size_db, guint32 avg_bitrate,
+ guint32 max_bitrate)
+{
+ AtomData *atom_data;
+ GstBuffer *buf;
+
+ if (buffer_size_db == 0 && avg_bitrate == 0 && max_bitrate == 0)
+ return 0;
+
+ buf = gst_buffer_new_and_alloc (12);
+
+ GST_WRITE_UINT32_BE (GST_BUFFER_DATA (buf), buffer_size_db);
+ GST_WRITE_UINT32_BE (GST_BUFFER_DATA (buf) + 4, max_bitrate);
+ GST_WRITE_UINT32_BE (GST_BUFFER_DATA (buf) + 8, avg_bitrate);
+
+ atom_data =
+ atom_data_new_from_gst_buffer (GST_MAKE_FOURCC ('b', 't', 'r', 't'), buf);
+ gst_buffer_unref (buf);
+
+ return build_atom_info_wrapper ((Atom *) atom_data, atom_data_copy_data,
+ atom_data_free);
+}
+
+static AtomInfo *
+build_mov_wave_extension (AtomTRAK * trak, guint32 fourcc, AtomInfo * atom1,
+ AtomInfo * atom2, gboolean terminator)
+{
+ AtomWAVE *wave;
+ AtomFRMA *frma;
+ Atom *ext_atom;
+
+ /* Build WAVE atom for sample table entry */
+ wave = atom_wave_new ();
+
+ /* Prepend Terminator atom to the WAVE list first, so it ends up last */
+ if (terminator) {
+ 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 supplied atoms to WAVE */
+ if (atom2)
+ wave->extension_atoms = g_list_prepend (wave->extension_atoms, atom2);
+ if (atom1)
+ wave->extension_atoms = g_list_prepend (wave->extension_atoms, atom1);
+
+ /* Add FRMA to the WAVE */
+ frma = atom_frma_new ();
+ frma->media_type = fourcc;
+
+ 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, atom_wave_copy_data,
+ atom_wave_free);
+}
+
+AtomInfo *
+build_mov_aac_extension (AtomTRAK * trak, const GstBuffer * codec_data,
+ guint32 avg_bitrate, guint32 max_bitrate)
+{
+ AtomInfo *esds, *mp4a;
+ GstBuffer *buf;
+
+ /* Add ESDS atom to WAVE */
+ esds = build_esds_extension (trak, ESDS_OBJECT_TYPE_MPEG4_P3,
+ ESDS_STREAM_TYPE_AUDIO, codec_data, avg_bitrate, max_bitrate);
+
+ /* 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;
+ mp4a = build_codec_data_extension (FOURCC_mp4a, buf);
+ gst_buffer_unref (buf);
+
+ return build_mov_wave_extension (trak, FOURCC_mp4a, mp4a, esds, TRUE);
+}
+
+AtomInfo *
+build_mov_alac_extension (AtomTRAK * trak, const GstBuffer * codec_data)
+{
+ AtomInfo *alac;
+
+ alac = build_codec_data_extension (FOURCC_alac, codec_data);
+
+ return build_mov_wave_extension (trak, FOURCC_alac, NULL, alac, TRUE);
+}
+
+AtomInfo *
+build_fiel_extension (gint fields)
+{
+ AtomData *atom_data;
+ GstBuffer *buf;
+
+ if (fields == 1) {
+ return NULL;
+ }
+
+ buf = gst_buffer_new_and_alloc (1);
+ GST_BUFFER_DATA (buf)[0] = (guint8) fields;
+
+ atom_data =
+ atom_data_new_from_gst_buffer (GST_MAKE_FOURCC ('f', 'i', 'e', 'l'), buf);
+ gst_buffer_unref (buf);
+
+ return build_atom_info_wrapper ((Atom *) atom_data, atom_data_copy_data,
+ atom_data_free);
+}
+
+AtomInfo *
+build_jp2x_extension (const GstBuffer * prefix)
+{
+ AtomData *atom_data;
+
+ if (!prefix) {
+ return NULL;
+ }
+
+ atom_data =
+ atom_data_new_from_gst_buffer (GST_MAKE_FOURCC ('j', 'p', '2', 'x'),
+ prefix);
+
+ return build_atom_info_wrapper ((Atom *) atom_data, atom_data_copy_data,
+ atom_data_free);
+}
+
+AtomInfo *
+build_jp2h_extension (AtomTRAK * trak, gint width, gint height, guint32 fourcc,
+ gint ncomp, const GValue * cmap_array, const GValue * cdef_array)
+{
+ AtomData *atom_data;
+ GstBuffer *buf;
+ guint8 cenum;
+ gint i;
+ gint idhr_size = 22;
+ gint colr_size = 15;
+ gint cmap_size = 0, cdef_size = 0;
+ gint cmap_array_size = 0;
+ gint cdef_array_size = 0;
+ GstByteWriter writer;
+
+ g_return_val_if_fail (cmap_array == NULL ||
+ GST_VALUE_HOLDS_ARRAY (cmap_array), NULL);
+ g_return_val_if_fail (cdef_array == NULL ||
+ GST_VALUE_HOLDS_ARRAY (cdef_array), NULL);
+
+ if (fourcc == GST_MAKE_FOURCC ('s', 'R', 'G', 'B')) {
+ cenum = 0x10;
+ if (ncomp == 0)
+ ncomp = 3;
+ } else if (fourcc == GST_MAKE_FOURCC ('G', 'R', 'A', 'Y')) {
+ cenum = 0x11;
+ if (ncomp == 0)
+ ncomp = 1;
+ } else if (fourcc == GST_MAKE_FOURCC ('s', 'Y', 'U', 'V')) {
+ cenum = 0x12;
+ if (ncomp == 0)
+ ncomp = 3;
+ } else
+ return NULL;
+
+ if (cmap_array) {
+ cmap_array_size = gst_value_array_get_size (cmap_array);
+ cmap_size = 8 + cmap_array_size * 4;
+ }
+ if (cdef_array) {
+ cdef_array_size = gst_value_array_get_size (cdef_array);
+ cdef_size = 8 + 2 + cdef_array_size * 6;
+ }
+
+ buf = gst_buffer_new_and_alloc (idhr_size + colr_size + cmap_size +
+ cdef_size);
+ gst_byte_writer_init_with_buffer (&writer, buf, FALSE);
+
+ /* ihdr = image header box */
+ gst_byte_writer_put_uint32_be (&writer, 22);
+ gst_byte_writer_put_uint32_le (&writer, GST_MAKE_FOURCC ('i', 'h', 'd', 'r'));
+ gst_byte_writer_put_uint32_be (&writer, height);
+ gst_byte_writer_put_uint32_be (&writer, width);
+ gst_byte_writer_put_uint16_be (&writer, ncomp);
+ /* 8 bits per component, unsigned */
+ gst_byte_writer_put_uint8 (&writer, 0x7);
+ /* compression type; reserved */
+ gst_byte_writer_put_uint8 (&writer, 0x7);
+ /* colour space (un)known */
+ gst_byte_writer_put_uint8 (&writer, 0x0);
+ /* intellectual property right (box present) */
+ gst_byte_writer_put_uint8 (&writer, 0x0);
+
+ /* colour specification box */
+ gst_byte_writer_put_uint32_be (&writer, 15);
+ gst_byte_writer_put_uint32_le (&writer, GST_MAKE_FOURCC ('c', 'o', 'l', 'r'));
+
+ /* specification method: enumerated */
+ gst_byte_writer_put_uint8 (&writer, 0x1);
+ /* precedence; reserved */
+ gst_byte_writer_put_uint8 (&writer, 0x0);
+ /* approximation; reserved */
+ gst_byte_writer_put_uint8 (&writer, 0x0);
+ /* enumerated colourspace */
+ gst_byte_writer_put_uint32_be (&writer, cenum);
+
+ if (cmap_array) {
+ gst_byte_writer_put_uint32_be (&writer, cmap_size);
+ gst_byte_writer_put_uint32_le (&writer,
+ GST_MAKE_FOURCC ('c', 'm', 'a', 'p'));
+ for (i = 0; i < cmap_array_size; i++) {
+ const GValue *item;
+ gint value;
+ guint16 cmp;
+ guint8 mtyp;
+ guint8 pcol;
+ item = gst_value_array_get_value (cmap_array, i);
+ value = g_value_get_int (item);
+
+ /* value is '(mtyp << 24) | (pcol << 16) | cmp' */
+ cmp = value & 0xFFFF;
+ mtyp = value >> 24;
+ pcol = (value >> 16) & 0xFF;
+
+ if (mtyp == 1)
+ GST_WARNING ("MTYP of cmap atom signals Pallete Mapping, but we don't "
+ "handle Pallete mapping atoms yet");
+
+ gst_byte_writer_put_uint16_be (&writer, cmp);
+ gst_byte_writer_put_uint8 (&writer, mtyp);
+ gst_byte_writer_put_uint8 (&writer, pcol);
+ }
+ }
+
+ if (cdef_array) {
+ gst_byte_writer_put_uint32_be (&writer, cdef_size);
+ gst_byte_writer_put_uint32_le (&writer,
+ GST_MAKE_FOURCC ('c', 'd', 'e', 'f'));
+ gst_byte_writer_put_uint16_be (&writer, cdef_array_size);
+ for (i = 0; i < cdef_array_size; i++) {
+ const GValue *item;
+ gint value;
+ item = gst_value_array_get_value (cdef_array, i);
+ value = g_value_get_int (item);
+
+ gst_byte_writer_put_uint16_be (&writer, i);
+ if (value > 0) {
+ gst_byte_writer_put_uint16_be (&writer, 0);
+ gst_byte_writer_put_uint16_be (&writer, value);
+ } else if (value < 0) {
+ gst_byte_writer_put_uint16_be (&writer, -value);
+ gst_byte_writer_put_uint16_be (&writer, 0); /* TODO what here? */
+ } else {
+ gst_byte_writer_put_uint16_be (&writer, 1);
+ gst_byte_writer_put_uint16_be (&writer, 0);
+ }
+ }
+ }
+
+ g_assert (gst_byte_writer_get_remaining (&writer) == 0);
+
+ atom_data = atom_data_new_from_gst_buffer (FOURCC_jp2h, buf);
+ gst_buffer_unref (buf);
+
+ return build_atom_info_wrapper ((Atom *) atom_data, atom_data_copy_data,
+ 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, atom_data_copy_data,
+ atom_data_free);
+ }
+
+ return result;
+}
+
+AtomInfo *
+build_amr_extension (void)
+{
+ 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 (void)
+{
+ 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;
+}
+
+AtomInfo *
+build_gama_atom (gdouble gamma)
+{
+ AtomInfo *res;
+ guint32 gamma_fp;
+ GstBuffer *buf;
+
+ /* convert to uint32 from fixed point */
+ gamma_fp = (guint32) 65536 *gamma;
+
+ buf = gst_buffer_new_and_alloc (4);
+ GST_WRITE_UINT32_BE (GST_BUFFER_DATA (buf), gamma_fp);
+ res = build_codec_data_extension (FOURCC_gama, buf);
+ gst_buffer_unref (buf);
+ return res;
+}
+
+AtomInfo *
+build_SMI_atom (const GstBuffer * seqh)
+{
+ AtomInfo *res;
+ GstBuffer *buf;
+
+ /* the seqh plus its size and fourcc */
+ buf = gst_buffer_new_and_alloc (GST_BUFFER_SIZE (seqh) + 8);
+
+ GST_WRITE_UINT32_LE (GST_BUFFER_DATA (buf), FOURCC_SEQH);
+ GST_WRITE_UINT32_BE (GST_BUFFER_DATA (buf) + 4, GST_BUFFER_SIZE (seqh));
+ memcpy (GST_BUFFER_DATA (buf) + 8, GST_BUFFER_DATA (seqh),
+ GST_BUFFER_SIZE (seqh));
+ res = build_codec_data_extension (FOURCC_SMI_, buf);
+ gst_buffer_unref (buf);
+ return res;
+}
+
+static AtomInfo *
+build_ima_adpcm_atom (gint channels, gint rate, gint blocksize)
+{
+ AtomData *atom_data;
+ GstBuffer *buf;
+ guint8 *data;
+ const gint ima_adpcm_atom_size = 20;
+ guint32 fourcc;
+ gint samplesperblock;
+ gint bytespersec;
+
+ /* The FOURCC for WAV codecs in QT is 'ms' followed by the 16 bit wave codec
+ identifier. Note that the identifier here is big-endian, but when used
+ within the WAVE header (below), it's little endian. */
+ fourcc = MS_WAVE_FOURCC (0x11);
+
+ buf = gst_buffer_new_and_alloc (ima_adpcm_atom_size);
+ data = GST_BUFFER_DATA (buf);
+
+ /* This atom's content is a WAVE header, including 2 bytes of extra data.
+ Note that all of this is little-endian, unlike most stuff in qt. */
+ /* 4 bytes header per channel (including 1 sample). Then 2 samples per byte
+ for the rest. Simplifies to this. */
+ samplesperblock = 2 * blocksize / channels - 7;
+ bytespersec = rate * blocksize / samplesperblock;
+ GST_WRITE_UINT16_LE (data, 0x11);
+ GST_WRITE_UINT16_LE (data + 2, channels);
+ GST_WRITE_UINT32_LE (data + 4, rate);
+ GST_WRITE_UINT32_LE (data + 8, bytespersec);
+ GST_WRITE_UINT16_LE (data + 12, blocksize);
+ GST_WRITE_UINT16_LE (data + 14, 4);
+ GST_WRITE_UINT16_LE (data + 16, 2); /* Two extra bytes */
+ GST_WRITE_UINT16_LE (data + 18, samplesperblock);
+
+ atom_data = atom_data_new_from_gst_buffer (fourcc, buf);
+ gst_buffer_unref (buf);
+
+ return build_atom_info_wrapper ((Atom *) atom_data, atom_data_copy_data,
+ atom_data_free);
+}
+
+AtomInfo *
+build_ima_adpcm_extension (gint channels, gint rate, gint blocksize)
+{
+ AtomWAVE *wave;
+ AtomFRMA *frma;
+ Atom *ext_atom;
+
+ /* Add WAVE atom */
+ 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 wave ima adpcm atom to WAVE */
+ wave->extension_atoms = g_list_prepend (wave->extension_atoms,
+ build_ima_adpcm_atom (channels, rate, blocksize));
+
+ /* Add FRMA to the WAVE */
+ frma = atom_frma_new ();
+ frma->media_type = MS_WAVE_FOURCC (0x11);
+
+ 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, atom_wave_copy_data,
+ atom_wave_free);
+}
+
+AtomInfo *
+build_uuid_xmp_atom (GstBuffer * xmp_data)
+{
+ AtomUUID *uuid;
+ static guint8 xmp_uuid[] = { 0xBE, 0x7A, 0xCF, 0xCB,
+ 0x97, 0xA9, 0x42, 0xE8,
+ 0x9C, 0x71, 0x99, 0x94,
+ 0x91, 0xE3, 0xAF, 0xAC
+ };
+
+ if (xmp_data == NULL)
+ return NULL;
+
+ uuid = atom_uuid_new ();
+ memcpy (uuid->uuid, xmp_uuid, 16);
+
+ uuid->data = g_malloc (GST_BUFFER_SIZE (xmp_data));
+ uuid->datalen = GST_BUFFER_SIZE (xmp_data);
+ memcpy (uuid->data, GST_BUFFER_DATA (xmp_data), GST_BUFFER_SIZE (xmp_data));
+
+ return build_atom_info_wrapper ((Atom *) uuid, atom_uuid_copy_data,
+ atom_uuid_free);
+}
diff --git a/gst/quicktime/atoms.h b/gst/quicktime/atoms.h
new file mode 100644
index 000000000..5aeb5f8f6
--- /dev/null
+++ b/gst/quicktime/atoms.h
@@ -0,0 +1,956 @@
+/* Quicktime muxer plugin for GStreamer
+ * Copyright (C) 2008-2010 Thiago 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"
+
+/* helper storage struct */
+#define ATOM_ARRAY(struct_type) \
+struct { \
+ guint size; \
+ guint len; \
+ struct_type *data; \
+}
+
+/* storage helpers */
+
+#define atom_array_init(array, reserve) \
+G_STMT_START { \
+ (array)->len = 0; \
+ (array)->size = reserve; \
+ (array)->data = g_malloc (sizeof (*(array)->data) * reserve); \
+} G_STMT_END
+
+#define atom_array_append(array, elmt, inc) \
+G_STMT_START { \
+ g_assert ((array)->data); \
+ g_assert (inc > 0); \
+ if (G_UNLIKELY ((array)->len == (array)->size)) { \
+ (array)->size += inc; \
+ (array)->data = \
+ g_realloc ((array)->data, sizeof (*((array)->data)) * (array)->size); \
+ } \
+ (array)->data[(array)->len] = elmt; \
+ (array)->len++; \
+} G_STMT_END
+
+#define atom_array_get_len(array) ((array)->len)
+#define atom_array_index(array, index) ((array)->data[index])
+
+#define atom_array_clear(array) \
+G_STMT_START { \
+ (array)->size = (array)->len = 0; \
+ g_free ((array)->data); \
+ (array)->data = NULL; \
+} G_STMT_END
+
+/* 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,
+ ATOMS_TREE_FLAVOR_ISML
+} 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 _AtomUUID
+{
+ Atom header;
+
+ guint8 uuid[16];
+
+ /* not written */
+ guint32 datalen;
+
+ guint8 *data;
+} AtomUUID;
+
+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;
+
+ ATOM_ARRAY (STTSEntry) entries;
+} AtomSTTS;
+
+typedef struct _AtomSTSS
+{
+ AtomFull header;
+
+ ATOM_ARRAY (guint32) 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;
+ ATOM_ARRAY (guint32) entries;
+} AtomSTSZ;
+
+typedef struct _STSCEntry
+{
+ guint32 first_chunk;
+ guint32 samples_per_chunk;
+ guint32 sample_description_index;
+} STSCEntry;
+
+typedef struct _AtomSTSC
+{
+ AtomFull header;
+
+ ATOM_ARRAY (STSCEntry) 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;
+
+ ATOM_ARRAY (guint64) entries;
+} AtomSTCO64;
+
+typedef struct _CTTSEntry
+{
+ guint32 samplecount;
+ guint32 sampleoffset;
+} CTTSEntry;
+
+typedef struct _AtomCTTS
+{
+ AtomFull header;
+
+ /* also entry count here */
+ ATOM_ARRAY (CTTSEntry) entries;
+ gboolean do_pts;
+} 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 _EditListEntry
+{
+ /* duration in movie's timescale */
+ guint32 duration;
+ /* start time in media's timescale, -1 for empty */
+ guint32 media_time;
+ guint32 media_rate; /* fixed point 32 bit */
+} EditListEntry;
+
+typedef struct _AtomELST
+{
+ AtomFull header;
+
+ /* number of entries is implicit */
+ GSList *entries;
+} AtomELST;
+
+typedef struct _AtomEDTS
+{
+ Atom header;
+ AtomELST elst;
+} AtomEDTS;
+
+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;
+
+enum TrFlags
+{
+ TR_DATA_OFFSET = 0x01, /* data-offset-present */
+ TR_FIRST_SAMPLE_FLAGS = 0x04, /* first-sample-flags-present */
+ TR_SAMPLE_DURATION = 0x0100, /* sample-duration-present */
+ TR_SAMPLE_SIZE = 0x0200, /* sample-size-present */
+ TR_SAMPLE_FLAGS = 0x0400, /* sample-flags-present */
+ TR_COMPOSITION_TIME_OFFSETS = 0x0800 /* sample-composition-time-offsets-presents */
+};
+
+enum TfFlags
+{
+ TF_BASE_DATA_OFFSET = 0x01, /* base-data-offset-present */
+ TF_SAMPLE_DESCRIPTION_INDEX = 0x02, /* sample-description-index-present */
+ TF_DEFAULT_SAMPLE_DURATION = 0x08, /* default-sample-duration-present */
+ TF_DEFAULT_SAMPLE_SIZE = 0x010, /* default-sample-size-present */
+ TF_DEFAULT_SAMPLE_FLAGS = 0x020, /* default-sample-flags-present */
+ TF_DURATION_IS_EMPTY = 0x010000 /* sample-composition-time-offsets-presents */
+};
+
+typedef struct _AtomTRAK
+{
+ Atom header;
+
+ AtomTKHD tkhd;
+ AtomEDTS *edts;
+ AtomMDIA mdia;
+
+ /* some helper info for structural conformity checks */
+ gboolean is_video;
+ gboolean is_h264;
+} AtomTRAK;
+
+typedef struct _AtomTREX
+{
+ AtomFull header;
+
+ guint32 track_ID;
+ guint32 default_sample_description_index;
+ guint32 default_sample_duration;
+ guint32 default_sample_size;
+ guint32 default_sample_flags;
+} AtomTREX;
+
+typedef struct _AtomMEHD
+{
+ AtomFull header;
+
+ guint64 fragment_duration;
+} AtomMEHD;
+
+
+typedef struct _AtomMVEX
+{
+ Atom header;
+
+ AtomMEHD mehd;
+
+ /* list of AtomTREX */
+ GList *trexs;
+} AtomMVEX;
+
+typedef struct _AtomMFHD
+{
+ AtomFull header;
+
+ guint32 sequence_number;
+} AtomMFHD;
+
+typedef struct _AtomTFHD
+{
+ AtomFull header;
+
+ guint32 track_ID;
+ guint64 base_data_offset;
+ guint32 sample_description_index;
+ guint32 default_sample_duration;
+ guint32 default_sample_size;
+ guint32 default_sample_flags;
+} AtomTFHD;
+
+typedef struct _TRUNSampleEntry
+{
+ guint32 sample_duration;
+ guint32 sample_size;
+ guint32 sample_flags;
+ guint32 sample_composition_time_offset;
+} TRUNSampleEntry;
+
+typedef struct _AtomTRUN
+{
+ AtomFull header;
+
+ guint32 sample_count;
+ gint32 data_offset;
+ guint32 first_sample_flags;
+
+ /* array of fields */
+ ATOM_ARRAY (TRUNSampleEntry) entries;
+} AtomTRUN;
+
+typedef struct _AtomSDTP
+{
+ AtomFull header;
+
+ /* not serialized */
+ guint32 sample_count;
+
+ /* array of fields */
+ ATOM_ARRAY (guint8) entries;
+} AtomSDTP;
+
+typedef struct _AtomTRAF
+{
+ Atom header;
+
+ AtomTFHD tfhd;
+
+ /* list of AtomTRUN */
+ GList *truns;
+ /* list of AtomSDTP */
+ GList *sdtps;
+} AtomTRAF;
+
+typedef struct _AtomMOOF
+{
+ Atom header;
+
+ AtomMFHD mfhd;
+
+ /* list of AtomTRAF */
+ GList *trafs;
+} AtomMOOF;
+
+
+typedef struct _AtomMOOV
+{
+ /* style */
+ AtomsContext context;
+
+ Atom header;
+
+ AtomMVHD mvhd;
+ AtomMVEX mvex;
+
+ /* list of AtomTRAK */
+ GList *traks;
+ AtomUDTA *udta;
+
+ gboolean fragmented;
+} AtomMOOV;
+
+typedef struct _AtomWAVE
+{
+ Atom header;
+
+ /* list of AtomInfo */
+ GList *extension_atoms;
+} AtomWAVE;
+
+typedef struct _TFRAEntry
+{
+ guint64 time;
+ guint64 moof_offset;
+ guint32 traf_number;
+ guint32 trun_number;
+ guint32 sample_number;
+} TFRAEntry;
+
+typedef struct _AtomTFRA
+{
+ AtomFull header;
+
+ guint32 track_ID;
+ guint32 lengths;
+ /* array of entries */
+ ATOM_ARRAY (TFRAEntry) entries;
+} AtomTFRA;
+
+typedef struct _AtomMFRA
+{
+ Atom header;
+
+ /* list of tfra */
+ GList *tfras;
+} AtomMFRA;
+
+/*
+ * 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,
+ gint64 pts_offset);
+void atom_trak_add_elst_entry (AtomTRAK * trak, guint32 duration,
+ guint32 media_time, guint32 rate);
+guint32 atom_trak_get_timescale (AtomTRAK *trak);
+guint32 atom_trak_get_id (AtomTRAK * trak);
+void atom_stbl_add_samples (AtomSTBL * stbl, guint32 nsamples,
+ guint32 delta, guint32 size,
+ guint64 chunk_offset, gboolean sync,
+ gint64 pts_offset);
+
+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_fragmented (AtomMOOV *moov, gboolean fragmented);
+void atom_moov_chunks_add_offset (AtomMOOV *moov, guint32 offset);
+void atom_moov_add_trak (AtomMOOV *moov, AtomTRAK *trak);
+
+guint64 atom_mvhd_copy_data (AtomMVHD * atom, guint8 ** buffer,
+ guint64 * size, guint64 * offset);
+void atom_stco64_chunks_add_offset (AtomSTCO64 * stco64, guint32 offset);
+guint64 atom_trak_copy_data (AtomTRAK * atom, guint8 ** buffer,
+ guint64 * size, guint64 * offset);
+void atom_stbl_clear (AtomSTBL * stbl);
+void atom_stbl_init (AtomSTBL * stbl);
+guint64 atom_stss_copy_data (AtomSTSS *atom, guint8 **buffer,
+ guint64 *size, guint64* offset);
+guint64 atom_stts_copy_data (AtomSTTS *atom, guint8 **buffer,
+ guint64 *size, guint64* offset);
+guint64 atom_stsc_copy_data (AtomSTSC *atom, guint8 **buffer,
+ guint64 *size, guint64* offset);
+guint64 atom_stsz_copy_data (AtomSTSZ *atom, guint8 **buffer,
+ guint64 *size, guint64* offset);
+guint64 atom_ctts_copy_data (AtomCTTS *atom, guint8 **buffer,
+ guint64 *size, guint64* offset);
+guint64 atom_stco64_copy_data (AtomSTCO64 *atom, guint8 **buffer,
+ guint64 *size, guint64* offset);
+AtomMOOF* atom_moof_new (AtomsContext *context, guint32 sequence_number);
+void atom_moof_free (AtomMOOF *moof);
+guint64 atom_moof_copy_data (AtomMOOF *moof, guint8 **buffer, guint64 *size, guint64* offset);
+AtomTRAF * atom_traf_new (AtomsContext * context, guint32 track_ID);
+void atom_traf_free (AtomTRAF * traf);
+void atom_traf_add_samples (AtomTRAF * traf, guint32 delta,
+ guint32 size, gboolean sync, gint64 pts_offset,
+ gboolean sdtp_sync);
+guint32 atom_traf_get_sample_num (AtomTRAF * traf);
+void atom_moof_add_traf (AtomMOOF *moof, AtomTRAF *traf);
+
+AtomMFRA* atom_mfra_new (AtomsContext *context);
+void atom_mfra_free (AtomMFRA *mfra);
+AtomTFRA* atom_tfra_new (AtomsContext *context, guint32 track_ID);
+void atom_tfra_add_entry (AtomTFRA *tfra, guint64 dts, guint32 sample_num);
+void atom_tfra_update_offset (AtomTFRA * tfra, guint64 offset);
+void atom_mfra_add_tfra (AtomMFRA *mfra, AtomTFRA *tfra);
+guint64 atom_mfra_copy_data (AtomMFRA *mfra, guint8 **buffer, guint64 *size, guint64* offset);
+
+
+/* media sample description related helpers */
+
+typedef struct
+{
+ guint16 version;
+ 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,
+ GList * ext_atoms_list);
+
+AtomInfo * build_codec_data_extension (guint32 fourcc, const GstBuffer * codec_data);
+AtomInfo * build_mov_aac_extension (AtomTRAK * trak, const GstBuffer * codec_data,
+ guint32 avg_bitrate, guint32 max_bitrate);
+AtomInfo * build_mov_alac_extension (AtomTRAK * trak, const GstBuffer * codec_data);
+AtomInfo * build_esds_extension (AtomTRAK * trak, guint8 object_type,
+ guint8 stream_type, const GstBuffer * codec_data,
+ guint32 avg_bitrate, guint32 max_bitrate);
+AtomInfo * build_btrt_extension (guint32 buffer_size_db, guint32 avg_bitrate,
+ guint32 max_bitrate);
+AtomInfo * build_jp2h_extension (AtomTRAK * trak, gint width, gint height,
+ guint32 fourcc, gint ncomp,
+ const GValue * cmap_array,
+ const GValue * cdef_array);
+
+AtomInfo * build_jp2x_extension (const GstBuffer * prefix);
+AtomInfo * build_fiel_extension (gint fields);
+AtomInfo * build_amr_extension (void);
+AtomInfo * build_h263_extension (void);
+AtomInfo * build_gama_atom (gdouble gamma);
+AtomInfo * build_SMI_atom (const GstBuffer *seqh);
+AtomInfo * build_ima_adpcm_extension (gint channels, gint rate,
+ gint blocksize);
+AtomInfo * build_uuid_xmp_atom (GstBuffer * xmp);
+
+
+/*
+ * 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);
+
+void atom_moov_add_xmp_tags (AtomMOOV * moov, GstBuffer * xmp);
+
+#define GST_QT_MUX_DEFAULT_TAG_LANGUAGE "eng"
+guint16 language_code (const char * lang);
+
+#endif /* __ATOMS_H__ */
diff --git a/gst/quicktime/atomsrecovery.c b/gst/quicktime/atomsrecovery.c
new file mode 100644
index 000000000..1f5a287d1
--- /dev/null
+++ b/gst/quicktime/atomsrecovery.c
@@ -0,0 +1,1095 @@
+/* Quicktime muxer plugin for GStreamer
+ * Copyright (C) 2010 Thiago Santos <thiago.sousa.santos@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.
+ */
+/*
+ * 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.
+ */
+
+/**
+ * This module contains functions for serializing partial information from
+ * a mux in progress (by qtmux elements). This enables reconstruction of the
+ * moov box if a crash happens and thus recovering the movie file.
+ *
+ * Usage:
+ * 1) pipeline: ...yourelements ! qtmux moov-recovery-file=path.mrf ! \
+ * filesink location=moovie.mov
+ *
+ * 2) CRASH!
+ *
+ * 3) gst-launch qtmoovrecover recovery-input=path.mrf broken-input=moovie.mov \
+ fixed-output=recovered.mov
+ *
+ * 4) (Hopefully) enjoy recovered.mov.
+ *
+ * --- Recovery file layout ---
+ * 1) Version (a guint16)
+ * 2) Prefix atom (if present)
+ * 3) ftyp atom
+ * 4) MVHD atom (without timescale/duration set)
+ * 5) moovie timescale
+ * 6) number of traks
+ * 7) list of trak atoms (stbl data is ignored, except for the stsd atom)
+ * 8) Buffers metadata (metadata that is relevant to the container)
+ * Buffers metadata are stored in the order they are added to the mdat,
+ * each entre has a fixed size and is stored in BE. booleans are stored
+ * as a single byte where 0 means false, otherwise is true.
+ * Metadata:
+ * - guint32 track_id;
+ * - guint32 nsamples;
+ * - guint32 delta;
+ * - guint32 size;
+ * - guint64 chunk_offset;
+ * - gboolean sync;
+ * - gboolean do_pts;
+ * - guint64 pts_offset; (always present, ignored if do_pts is false)
+ *
+ * The mdat file might contain ftyp and then mdat, in case this is the faststart
+ * temporary file there is no ftyp and no mdat header, only the buffers data.
+ *
+ * Notes about recovery file layout: We still don't store tags nor EDTS data.
+ *
+ * IMPORTANT: this is still at a experimental state.
+ */
+
+#include "atomsrecovery.h"
+
+#define ATOMS_RECOV_OUTPUT_WRITE_ERROR(err) \
+ g_set_error (err, ATOMS_RECOV_QUARK, ATOMS_RECOV_ERR_FILE, \
+ "Failed to write to output file: %s", g_strerror (errno))
+
+static gboolean
+atoms_recov_write_version (FILE * f)
+{
+ guint8 data[2];
+ GST_WRITE_UINT16_BE (data, ATOMS_RECOV_FILE_VERSION);
+ return fwrite (data, 2, 1, f) == 1;
+}
+
+static gboolean
+atoms_recov_write_ftyp_info (FILE * f, AtomFTYP * ftyp, GstBuffer * prefix)
+{
+ guint8 *data = NULL;
+ guint64 offset = 0;
+ guint64 size = 0;
+
+ if (prefix) {
+ if (fwrite (GST_BUFFER_DATA (prefix), 1, GST_BUFFER_SIZE (prefix), f) !=
+ GST_BUFFER_SIZE (prefix)) {
+ return FALSE;
+ }
+ }
+ if (!atom_ftyp_copy_data (ftyp, &data, &size, &offset)) {
+ return FALSE;
+ }
+ if (fwrite (data, 1, offset, f) != offset) {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/**
+ * Writes important info on the 'moov' atom (non-trak related)
+ * to be able to recover the moov structure after a crash.
+ *
+ * Currently, it writes the MVHD atom.
+ */
+static gboolean
+atoms_recov_write_moov_info (FILE * f, AtomMOOV * moov)
+{
+ guint8 *data;
+ guint64 size;
+ guint64 offset = 0;
+ guint64 atom_size = 0;
+ gint writen = 0;
+
+ /* likely enough */
+ size = 256;
+ data = g_malloc (size);
+ atom_size = atom_mvhd_copy_data (&moov->mvhd, &data, &size, &offset);
+ if (atom_size > 0)
+ writen = fwrite (data, 1, atom_size, f);
+ g_free (data);
+ return atom_size > 0 && writen == atom_size;
+}
+
+/**
+ * Writes the number of traks to the file.
+ * This simply writes a guint32 in BE.
+ */
+static gboolean
+atoms_recov_write_traks_number (FILE * f, guint32 traks)
+{
+ guint8 data[4];
+ GST_WRITE_UINT32_BE (data, traks);
+ return fwrite (data, 4, 1, f) == 1;
+}
+
+/**
+ * Writes the moov's timescale to the file
+ * This simply writes a guint32 in BE.
+ */
+static gboolean
+atoms_recov_write_moov_timescale (FILE * f, guint32 timescale)
+{
+ guint8 data[4];
+ GST_WRITE_UINT32_BE (data, timescale);
+ return fwrite (data, 4, 1, f) == 1;
+}
+
+/**
+ * Writes the trak atom to the file.
+ */
+gboolean
+atoms_recov_write_trak_info (FILE * f, AtomTRAK * trak)
+{
+ guint8 *data;
+ guint64 size;
+ guint64 offset = 0;
+ guint64 atom_size = 0;
+ gint writen = 0;
+
+ /* buffer is realloced to a larger size if needed */
+ size = 4 * 1024;
+ data = g_malloc (size);
+ atom_size = atom_trak_copy_data (trak, &data, &size, &offset);
+ if (atom_size > 0)
+ writen = fwrite (data, atom_size, 1, f);
+ g_free (data);
+ return atom_size > 0 && writen == atom_size;
+}
+
+gboolean
+atoms_recov_write_trak_samples (FILE * f, AtomTRAK * trak, guint32 nsamples,
+ guint32 delta, guint32 size, guint64 chunk_offset, gboolean sync,
+ gboolean do_pts, gint64 pts_offset)
+{
+ guint8 data[TRAK_BUFFER_ENTRY_INFO_SIZE];
+ /*
+ * We have to write a TrakBufferEntryInfo
+ */
+ GST_WRITE_UINT32_BE (data + 0, trak->tkhd.track_ID);
+ GST_WRITE_UINT32_BE (data + 4, nsamples);
+ GST_WRITE_UINT32_BE (data + 8, delta);
+ GST_WRITE_UINT32_BE (data + 12, size);
+ GST_WRITE_UINT64_BE (data + 16, chunk_offset);
+ if (sync)
+ GST_WRITE_UINT8 (data + 24, 1);
+ else
+ GST_WRITE_UINT8 (data + 24, 0);
+ if (do_pts) {
+ GST_WRITE_UINT8 (data + 25, 1);
+ GST_WRITE_UINT64_BE (data + 26, pts_offset);
+ } else {
+ GST_WRITE_UINT8 (data + 25, 0);
+ GST_WRITE_UINT64_BE (data + 26, 0);
+ }
+
+ return fwrite (data, 1, TRAK_BUFFER_ENTRY_INFO_SIZE, f) ==
+ TRAK_BUFFER_ENTRY_INFO_SIZE;
+}
+
+gboolean
+atoms_recov_write_headers (FILE * f, AtomFTYP * ftyp, GstBuffer * prefix,
+ AtomMOOV * moov, guint32 timescale, guint32 traks_number)
+{
+ if (!atoms_recov_write_version (f)) {
+ return FALSE;
+ }
+
+ if (!atoms_recov_write_ftyp_info (f, ftyp, prefix)) {
+ return FALSE;
+ }
+
+ if (!atoms_recov_write_moov_info (f, moov)) {
+ return FALSE;
+ }
+
+ if (!atoms_recov_write_moov_timescale (f, timescale)) {
+ return FALSE;
+ }
+
+ if (!atoms_recov_write_traks_number (f, traks_number)) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+read_atom_header (FILE * f, guint32 * fourcc, guint32 * size)
+{
+ guint8 aux[8];
+
+ if (fread (aux, 1, 8, f) != 8)
+ return FALSE;
+ *size = GST_READ_UINT32_BE (aux);
+ *fourcc = GST_READ_UINT32_LE (aux + 4);
+ return TRUE;
+}
+
+static gboolean
+moov_recov_file_parse_prefix (MoovRecovFile * moovrf)
+{
+ guint32 fourcc;
+ guint32 size;
+ guint32 total_size = 0;
+ if (fseek (moovrf->file, 2, SEEK_SET) != 0)
+ return FALSE;
+ if (!read_atom_header (moovrf->file, &fourcc, &size)) {
+ return FALSE;
+ }
+
+ if (fourcc != FOURCC_ftyp) {
+ /* we might have a prefix here */
+ if (fseek (moovrf->file, size - 8, SEEK_CUR) != 0)
+ return FALSE;
+
+ total_size += size;
+
+ /* now read the ftyp */
+ if (!read_atom_header (moovrf->file, &fourcc, &size))
+ return FALSE;
+ }
+
+ /* this has to be the ftyp */
+ if (fourcc != FOURCC_ftyp)
+ return FALSE;
+ total_size += size;
+ moovrf->prefix_size = total_size;
+ return fseek (moovrf->file, size - 8, SEEK_CUR) == 0;
+}
+
+static gboolean
+moov_recov_file_parse_mvhd (MoovRecovFile * moovrf)
+{
+ guint32 fourcc;
+ guint32 size;
+ if (!read_atom_header (moovrf->file, &fourcc, &size)) {
+ return FALSE;
+ }
+ /* check for sanity */
+ if (fourcc != FOURCC_mvhd)
+ return FALSE;
+
+ moovrf->mvhd_size = size;
+ moovrf->mvhd_pos = ftell (moovrf->file) - 8;
+
+ /* skip the remaining of the mvhd in the file */
+ return fseek (moovrf->file, size - 8, SEEK_CUR) == 0;
+}
+
+static gboolean
+mdat_recov_file_parse_mdat_start (MdatRecovFile * mdatrf)
+{
+ guint32 fourcc, size;
+
+ if (!read_atom_header (mdatrf->file, &fourcc, &size)) {
+ return FALSE;
+ }
+ if (size == 1) {
+ mdatrf->mdat_header_size = 16;
+ mdatrf->mdat_size = 16;
+ } else {
+ mdatrf->mdat_header_size = 8;
+ mdatrf->mdat_size = 8;
+ }
+ mdatrf->mdat_start = ftell (mdatrf->file) - 8;
+
+ return fourcc == FOURCC_mdat;
+}
+
+MdatRecovFile *
+mdat_recov_file_create (FILE * file, gboolean datafile, GError ** err)
+{
+ MdatRecovFile *mrf = g_new0 (MdatRecovFile, 1);
+ guint32 fourcc, size;
+
+ g_return_val_if_fail (file != NULL, NULL);
+
+ mrf->file = file;
+ mrf->rawfile = datafile;
+
+ /* get the file/data length */
+ if (fseek (file, 0, SEEK_END) != 0)
+ goto file_length_error;
+ /* still needs to deduce the mdat header and ftyp size */
+ mrf->data_size = ftell (file);
+ if (mrf->data_size == -1L)
+ goto file_length_error;
+
+ if (fseek (file, 0, SEEK_SET) != 0)
+ goto file_seek_error;
+
+ if (datafile) {
+ /* this file contains no atoms, only raw data to be placed on the mdat
+ * this happens when faststart mode is used */
+ mrf->mdat_start = 0;
+ mrf->mdat_header_size = 16;
+ mrf->mdat_size = 16;
+ return mrf;
+ }
+
+ if (!read_atom_header (file, &fourcc, &size)) {
+ goto parse_error;
+ }
+ if (fourcc != FOURCC_ftyp) {
+ /* this could be a prefix atom, let's skip it and try again */
+ if (fseek (file, size - 8, SEEK_CUR) != 0) {
+ goto file_seek_error;
+ }
+ if (!read_atom_header (file, &fourcc, &size)) {
+ goto parse_error;
+ }
+ }
+
+ if (fourcc != FOURCC_ftyp) {
+ goto parse_error;
+ }
+ if (fseek (file, size - 8, SEEK_CUR) != 0)
+ goto file_seek_error;
+
+ /* we don't parse this if we have a tmpdatafile */
+ if (!mdat_recov_file_parse_mdat_start (mrf)) {
+ g_set_error (err, ATOMS_RECOV_QUARK, ATOMS_RECOV_ERR_PARSING,
+ "Error while parsing mdat atom");
+ goto fail;
+ }
+
+ return mrf;
+
+parse_error:
+ g_set_error (err, ATOMS_RECOV_QUARK, ATOMS_RECOV_ERR_FILE,
+ "Failed to parse atom");
+ goto fail;
+
+file_seek_error:
+ g_set_error (err, ATOMS_RECOV_QUARK, ATOMS_RECOV_ERR_FILE,
+ "Failed to seek to start of the file");
+ goto fail;
+
+file_length_error:
+ g_set_error (err, ATOMS_RECOV_QUARK, ATOMS_RECOV_ERR_FILE,
+ "Failed to determine file size");
+ goto fail;
+
+fail:
+ mdat_recov_file_free (mrf);
+ return NULL;
+}
+
+void
+mdat_recov_file_free (MdatRecovFile * mrf)
+{
+ fclose (mrf->file);
+ g_free (mrf);
+}
+
+static gboolean
+moov_recov_parse_num_traks (MoovRecovFile * moovrf)
+{
+ guint8 traks[4];
+ if (fread (traks, 1, 4, moovrf->file) != 4)
+ return FALSE;
+ moovrf->num_traks = GST_READ_UINT32_BE (traks);
+ return TRUE;
+}
+
+static gboolean
+moov_recov_parse_moov_timescale (MoovRecovFile * moovrf)
+{
+ guint8 ts[4];
+ if (fread (ts, 1, 4, moovrf->file) != 4)
+ return FALSE;
+ moovrf->timescale = GST_READ_UINT32_BE (ts);
+ return TRUE;
+}
+
+static gboolean
+skip_atom (MoovRecovFile * moovrf, guint32 expected_fourcc)
+{
+ guint32 size;
+ guint32 fourcc;
+
+ if (!read_atom_header (moovrf->file, &fourcc, &size))
+ return FALSE;
+ if (fourcc != expected_fourcc)
+ return FALSE;
+
+ return (fseek (moovrf->file, size - 8, SEEK_CUR) == 0);
+}
+
+static gboolean
+moov_recov_parse_tkhd (MoovRecovFile * moovrf, TrakRecovData * trakrd)
+{
+ guint32 size;
+ guint32 fourcc;
+ guint8 data[4];
+
+ /* make sure we are on a tkhd atom */
+ if (!read_atom_header (moovrf->file, &fourcc, &size))
+ return FALSE;
+ if (fourcc != FOURCC_tkhd)
+ return FALSE;
+
+ trakrd->tkhd_file_offset = ftell (moovrf->file) - 8;
+
+ /* move 8 bytes forward to the trak_id pos */
+ if (fseek (moovrf->file, 12, SEEK_CUR) != 0)
+ return FALSE;
+ if (fread (data, 1, 4, moovrf->file) != 4)
+ return FALSE;
+
+ /* advance the rest of tkhd */
+ fseek (moovrf->file, 68, SEEK_CUR);
+
+ trakrd->trak_id = GST_READ_UINT32_BE (data);
+ return TRUE;
+}
+
+static gboolean
+moov_recov_parse_stbl (MoovRecovFile * moovrf, TrakRecovData * trakrd)
+{
+ guint32 size;
+ guint32 fourcc;
+ guint32 auxsize;
+
+ if (!read_atom_header (moovrf->file, &fourcc, &size))
+ return FALSE;
+ if (fourcc != FOURCC_stbl)
+ return FALSE;
+
+ trakrd->stbl_file_offset = ftell (moovrf->file) - 8;
+ trakrd->stbl_size = size;
+
+ /* skip the stsd */
+ if (!read_atom_header (moovrf->file, &fourcc, &auxsize))
+ return FALSE;
+ if (fourcc != FOURCC_stsd)
+ return FALSE;
+ if (fseek (moovrf->file, auxsize - 8, SEEK_CUR) != 0)
+ return FALSE;
+
+ trakrd->stsd_size = auxsize;
+ trakrd->post_stsd_offset = ftell (moovrf->file);
+
+ /* as this is the last atom we parse, we don't skip forward */
+
+ return TRUE;
+}
+
+static gboolean
+moov_recov_parse_minf (MoovRecovFile * moovrf, TrakRecovData * trakrd)
+{
+ guint32 size;
+ guint32 fourcc;
+ guint32 auxsize;
+
+ if (!read_atom_header (moovrf->file, &fourcc, &size))
+ return FALSE;
+ if (fourcc != FOURCC_minf)
+ return FALSE;
+
+ trakrd->minf_file_offset = ftell (moovrf->file) - 8;
+ trakrd->minf_size = size;
+
+ /* skip either of vmhd, smhd, hmhd that might follow */
+ if (!read_atom_header (moovrf->file, &fourcc, &auxsize))
+ return FALSE;
+ if (fourcc != FOURCC_vmhd && fourcc != FOURCC_smhd && fourcc != FOURCC_hmhd &&
+ fourcc != FOURCC_gmhd)
+ return FALSE;
+ if (fseek (moovrf->file, auxsize - 8, SEEK_CUR))
+ return FALSE;
+
+ /* skip a possible hdlr and the following dinf */
+ if (!read_atom_header (moovrf->file, &fourcc, &auxsize))
+ return FALSE;
+ if (fourcc == FOURCC_hdlr) {
+ if (fseek (moovrf->file, auxsize - 8, SEEK_CUR))
+ return FALSE;
+ if (!read_atom_header (moovrf->file, &fourcc, &auxsize))
+ return FALSE;
+ }
+ if (fourcc != FOURCC_dinf)
+ return FALSE;
+ if (fseek (moovrf->file, auxsize - 8, SEEK_CUR))
+ return FALSE;
+
+ /* now we are ready to read the stbl */
+ if (!moov_recov_parse_stbl (moovrf, trakrd))
+ return FALSE;
+
+ return TRUE;
+}
+
+static gboolean
+moov_recov_parse_mdhd (MoovRecovFile * moovrf, TrakRecovData * trakrd)
+{
+ guint32 size;
+ guint32 fourcc;
+ guint8 data[4];
+
+ /* make sure we are on a tkhd atom */
+ if (!read_atom_header (moovrf->file, &fourcc, &size))
+ return FALSE;
+ if (fourcc != FOURCC_mdhd)
+ return FALSE;
+
+ trakrd->mdhd_file_offset = ftell (moovrf->file) - 8;
+
+ /* get the timescale */
+ if (fseek (moovrf->file, 12, SEEK_CUR) != 0)
+ return FALSE;
+ if (fread (data, 1, 4, moovrf->file) != 4)
+ return FALSE;
+ trakrd->timescale = GST_READ_UINT32_BE (data);
+ if (fseek (moovrf->file, 8, SEEK_CUR) != 0)
+ return FALSE;
+ return TRUE;
+}
+
+static gboolean
+moov_recov_parse_mdia (MoovRecovFile * moovrf, TrakRecovData * trakrd)
+{
+ guint32 size;
+ guint32 fourcc;
+
+ /* make sure we are on a tkhd atom */
+ if (!read_atom_header (moovrf->file, &fourcc, &size))
+ return FALSE;
+ if (fourcc != FOURCC_mdia)
+ return FALSE;
+
+ trakrd->mdia_file_offset = ftell (moovrf->file) - 8;
+ trakrd->mdia_size = size;
+
+ if (!moov_recov_parse_mdhd (moovrf, trakrd))
+ return FALSE;
+
+ if (!skip_atom (moovrf, FOURCC_hdlr))
+ return FALSE;
+ if (!moov_recov_parse_minf (moovrf, trakrd))
+ return FALSE;
+ return TRUE;
+}
+
+static gboolean
+moov_recov_parse_trak (MoovRecovFile * moovrf, TrakRecovData * trakrd)
+{
+ guint64 offset;
+ guint32 size;
+ guint32 fourcc;
+
+ offset = ftell (moovrf->file);
+ if (offset == -1) {
+ return FALSE;
+ }
+
+ /* make sure we are on a trak atom */
+ if (!read_atom_header (moovrf->file, &fourcc, &size)) {
+ return FALSE;
+ }
+ if (fourcc != FOURCC_trak) {
+ return FALSE;
+ }
+ trakrd->trak_size = size;
+
+ /* now we should have a trak header 'tkhd' */
+ if (!moov_recov_parse_tkhd (moovrf, trakrd))
+ return FALSE;
+
+ /* FIXME add edts handling here and in qtmux, as this is only detected
+ * after buffers start flowing */
+
+ if (!moov_recov_parse_mdia (moovrf, trakrd))
+ return FALSE;
+
+ trakrd->file_offset = offset;
+ /* position after the trak */
+ return fseek (moovrf->file, (long int) offset + size, SEEK_SET) == 0;
+}
+
+MoovRecovFile *
+moov_recov_file_create (FILE * file, GError ** err)
+{
+ gint i;
+ MoovRecovFile *moovrf = g_new0 (MoovRecovFile, 1);
+
+ g_return_val_if_fail (file != NULL, NULL);
+
+ moovrf->file = file;
+
+ /* look for ftyp and prefix at the start */
+ if (!moov_recov_file_parse_prefix (moovrf)) {
+ g_set_error (err, ATOMS_RECOV_QUARK, ATOMS_RECOV_ERR_PARSING,
+ "Error while parsing prefix atoms");
+ goto fail;
+ }
+
+ /* parse the mvhd */
+ if (!moov_recov_file_parse_mvhd (moovrf)) {
+ g_set_error (err, ATOMS_RECOV_QUARK, ATOMS_RECOV_ERR_PARSING,
+ "Error while parsing mvhd atom");
+ goto fail;
+ }
+
+ if (!moov_recov_parse_moov_timescale (moovrf)) {
+ g_set_error (err, ATOMS_RECOV_QUARK, ATOMS_RECOV_ERR_PARSING,
+ "Error while parsing timescale");
+ goto fail;
+ }
+ if (!moov_recov_parse_num_traks (moovrf)) {
+ g_set_error (err, ATOMS_RECOV_QUARK, ATOMS_RECOV_ERR_PARSING,
+ "Error while parsing parsing number of traks");
+ goto fail;
+ }
+
+ /* init the traks */
+ moovrf->traks_rd = g_new0 (TrakRecovData, moovrf->num_traks);
+ for (i = 0; i < moovrf->num_traks; i++) {
+ atom_stbl_init (&(moovrf->traks_rd[i].stbl));
+ }
+ for (i = 0; i < moovrf->num_traks; i++) {
+ if (!moov_recov_parse_trak (moovrf, &(moovrf->traks_rd[i]))) {
+ g_set_error (err, ATOMS_RECOV_QUARK, ATOMS_RECOV_ERR_PARSING,
+ "Error while parsing trak atom");
+ goto fail;
+ }
+ }
+
+ return moovrf;
+
+fail:
+ moov_recov_file_free (moovrf);
+ return NULL;
+}
+
+void
+moov_recov_file_free (MoovRecovFile * moovrf)
+{
+ gint i;
+ fclose (moovrf->file);
+ if (moovrf->traks_rd) {
+ for (i = 0; i < moovrf->num_traks; i++) {
+ atom_stbl_clear (&(moovrf->traks_rd[i].stbl));
+ }
+ g_free (moovrf->traks_rd);
+ }
+ g_free (moovrf);
+}
+
+static gboolean
+moov_recov_parse_buffer_entry (MoovRecovFile * moovrf, TrakBufferEntryInfo * b)
+{
+ guint8 data[TRAK_BUFFER_ENTRY_INFO_SIZE];
+ gint read;
+
+ read = fread (data, 1, TRAK_BUFFER_ENTRY_INFO_SIZE, moovrf->file);
+ if (read != TRAK_BUFFER_ENTRY_INFO_SIZE)
+ return FALSE;
+
+ b->track_id = GST_READ_UINT32_BE (data);
+ b->nsamples = GST_READ_UINT32_BE (data + 4);
+ b->delta = GST_READ_UINT32_BE (data + 8);
+ b->size = GST_READ_UINT32_BE (data + 12);
+ b->chunk_offset = GST_READ_UINT64_BE (data + 16);
+ b->sync = data[24] != 0;
+ b->do_pts = data[25] != 0;
+ b->pts_offset = GST_READ_UINT64_BE (data + 26);
+ return TRUE;
+}
+
+static gboolean
+mdat_recov_add_sample (MdatRecovFile * mdatrf, guint32 size)
+{
+ /* test if this data exists */
+ if (mdatrf->mdat_size - mdatrf->mdat_header_size + size > mdatrf->data_size)
+ return FALSE;
+
+ mdatrf->mdat_size += size;
+ return TRUE;
+}
+
+static TrakRecovData *
+moov_recov_get_trak (MoovRecovFile * moovrf, guint32 id)
+{
+ gint i;
+ for (i = 0; i < moovrf->num_traks; i++) {
+ if (moovrf->traks_rd[i].trak_id == id)
+ return &(moovrf->traks_rd[i]);
+ }
+ return NULL;
+}
+
+static void
+trak_recov_data_add_sample (TrakRecovData * trak, TrakBufferEntryInfo * b)
+{
+ trak->duration += b->nsamples * b->delta;
+ atom_stbl_add_samples (&trak->stbl, b->nsamples, b->delta, b->size,
+ b->chunk_offset, b->sync, b->pts_offset);
+}
+
+/**
+ * Parses the buffer entries in the MoovRecovFile and matches the inputs
+ * with the data in the MdatRecovFile. Whenever a buffer entry of that
+ * represents 'x' bytes of data, the same amount of data is 'validated' in
+ * the MdatRecovFile and will be inluded in the generated moovie file.
+ */
+gboolean
+moov_recov_parse_buffers (MoovRecovFile * moovrf, MdatRecovFile * mdatrf,
+ GError ** err)
+{
+ TrakBufferEntryInfo entry;
+ TrakRecovData *trak;
+
+ /* we assume both moovrf and mdatrf are at the starting points of their
+ * data reading */
+ while (moov_recov_parse_buffer_entry (moovrf, &entry)) {
+ /* be sure we still have this data in mdat */
+ trak = moov_recov_get_trak (moovrf, entry.track_id);
+ if (trak == NULL) {
+ g_set_error (err, ATOMS_RECOV_QUARK, ATOMS_RECOV_ERR_PARSING,
+ "Invalid trak id found in buffer entry");
+ return FALSE;
+ }
+ if (!mdat_recov_add_sample (mdatrf, entry.size))
+ break;
+ trak_recov_data_add_sample (trak, &entry);
+ }
+ return TRUE;
+}
+
+static guint32
+trak_recov_data_get_trak_atom_size (TrakRecovData * trak)
+{
+ AtomSTBL *stbl = &trak->stbl;
+ guint64 offset;
+
+ /* write out our stbl child atoms */
+ offset = 0;
+
+ if (!atom_stts_copy_data (&stbl->stts, NULL, NULL, &offset)) {
+ goto fail;
+ }
+ if (atom_array_get_len (&stbl->stss.entries) > 0) {
+ if (!atom_stss_copy_data (&stbl->stss, NULL, NULL, &offset)) {
+ goto fail;
+ }
+ }
+ if (!atom_stsc_copy_data (&stbl->stsc, NULL, NULL, &offset)) {
+ goto fail;
+ }
+ if (!atom_stsz_copy_data (&stbl->stsz, NULL, NULL, &offset)) {
+ goto fail;
+ }
+ if (stbl->ctts) {
+ if (!atom_ctts_copy_data (stbl->ctts, NULL, NULL, &offset)) {
+ goto fail;
+ }
+ }
+ if (!atom_stco64_copy_data (&stbl->stco64, NULL, NULL, &offset)) {
+ goto fail;
+ }
+
+ return trak->trak_size + ((trak->stsd_size + offset + 8) - trak->stbl_size);
+
+fail:
+ return 0;
+}
+
+static guint8 *
+moov_recov_get_stbl_children_data (MoovRecovFile * moovrf, TrakRecovData * trak,
+ guint64 * p_size)
+{
+ AtomSTBL *stbl = &trak->stbl;
+ guint8 *buffer;
+ guint64 size;
+ guint64 offset;
+
+ /* write out our stbl child atoms
+ *
+ * Use 1MB as a starting size, *_copy_data functions
+ * will grow the buffer if needed.
+ */
+ size = 1024 * 1024;
+ buffer = g_malloc0 (size);
+ offset = 0;
+
+ if (!atom_stts_copy_data (&stbl->stts, &buffer, &size, &offset)) {
+ goto fail;
+ }
+ if (atom_array_get_len (&stbl->stss.entries) > 0) {
+ if (!atom_stss_copy_data (&stbl->stss, &buffer, &size, &offset)) {
+ goto fail;
+ }
+ }
+ if (!atom_stsc_copy_data (&stbl->stsc, &buffer, &size, &offset)) {
+ goto fail;
+ }
+ if (!atom_stsz_copy_data (&stbl->stsz, &buffer, &size, &offset)) {
+ goto fail;
+ }
+ if (stbl->ctts) {
+ if (!atom_ctts_copy_data (stbl->ctts, &buffer, &size, &offset)) {
+ goto fail;
+ }
+ }
+ if (!atom_stco64_copy_data (&stbl->stco64, &buffer, &size, &offset)) {
+ goto fail;
+ }
+ *p_size = offset;
+ return buffer;
+
+fail:
+ g_free (buffer);
+ return NULL;
+}
+
+gboolean
+moov_recov_write_file (MoovRecovFile * moovrf, MdatRecovFile * mdatrf,
+ FILE * outf, GError ** err)
+{
+ guint8 auxdata[16];
+ guint8 *data = NULL;
+ guint8 *prefix_data = NULL;
+ guint8 *mvhd_data = NULL;
+ guint8 *trak_data = NULL;
+ guint32 moov_size = 0;
+ gint i;
+ guint64 stbl_children_size = 0;
+ guint8 *stbl_children = NULL;
+ guint32 longest_duration = 0;
+ guint16 version;
+
+ /* check the version */
+ if (fseek (moovrf->file, 0, SEEK_SET) != 0) {
+ g_set_error (err, ATOMS_RECOV_QUARK, ATOMS_RECOV_ERR_FILE,
+ "Failed to seek to the start of the moov recovery file");
+ goto fail;
+ }
+ if (fread (auxdata, 1, 2, moovrf->file) != 2) {
+ g_set_error (err, ATOMS_RECOV_QUARK, ATOMS_RECOV_ERR_FILE,
+ "Failed to read version from file");
+ }
+
+ version = GST_READ_UINT16_BE (auxdata);
+ if (version != ATOMS_RECOV_FILE_VERSION) {
+ g_set_error (err, ATOMS_RECOV_QUARK, ATOMS_RECOV_ERR_VERSION,
+ "Input file version (%u) is not supported in this version (%u)",
+ version, ATOMS_RECOV_FILE_VERSION);
+ return FALSE;
+ }
+
+ /* write the ftyp */
+ prefix_data = g_malloc (moovrf->prefix_size);
+ if (fread (prefix_data, 1, moovrf->prefix_size,
+ moovrf->file) != moovrf->prefix_size) {
+ g_set_error (err, ATOMS_RECOV_QUARK, ATOMS_RECOV_ERR_FILE,
+ "Failed to read the ftyp atom from file");
+ goto fail;
+ }
+ if (fwrite (prefix_data, 1, moovrf->prefix_size, outf) != moovrf->prefix_size) {
+ ATOMS_RECOV_OUTPUT_WRITE_ERROR (err);
+ goto fail;
+ }
+ g_free (prefix_data);
+ prefix_data = NULL;
+
+ /* need to calculate the moov size beforehand to add the offset to
+ * chunk offset entries */
+ moov_size += moovrf->mvhd_size + 8; /* mvhd + moov size + fourcc */
+ for (i = 0; i < moovrf->num_traks; i++) {
+ TrakRecovData *trak = &(moovrf->traks_rd[i]);
+ guint32 duration; /* in moov's timescale */
+ guint32 trak_size;
+
+ /* convert trak duration to moov's duration */
+ duration = gst_util_uint64_scale_round (trak->duration, moovrf->timescale,
+ trak->timescale);
+
+ if (duration > longest_duration)
+ longest_duration = duration;
+ trak_size = trak_recov_data_get_trak_atom_size (trak);
+ if (trak_size == 0) {
+ g_set_error (err, ATOMS_RECOV_QUARK, ATOMS_RECOV_ERR_GENERIC,
+ "Failed to estimate trak atom size");
+ goto fail;
+ }
+ moov_size += trak_size;
+ }
+
+ /* add chunks offsets */
+ for (i = 0; i < moovrf->num_traks; i++) {
+ TrakRecovData *trak = &(moovrf->traks_rd[i]);
+ /* 16 for the mdat header */
+ gint64 offset = moov_size + ftell (outf) + 16;
+ atom_stco64_chunks_add_offset (&trak->stbl.stco64, offset);
+ }
+
+ /* write the moov */
+ GST_WRITE_UINT32_BE (auxdata, moov_size);
+ GST_WRITE_UINT32_LE (auxdata + 4, FOURCC_moov);
+ if (fwrite (auxdata, 1, 8, outf) != 8) {
+ ATOMS_RECOV_OUTPUT_WRITE_ERROR (err);
+ goto fail;
+ }
+
+ /* write the mvhd */
+ mvhd_data = g_malloc (moovrf->mvhd_size);
+ if (fseek (moovrf->file, moovrf->mvhd_pos, SEEK_SET) != 0)
+ goto fail;
+ if (fread (mvhd_data, 1, moovrf->mvhd_size,
+ moovrf->file) != moovrf->mvhd_size)
+ goto fail;
+ GST_WRITE_UINT32_BE (mvhd_data + 20, moovrf->timescale);
+ GST_WRITE_UINT32_BE (mvhd_data + 24, longest_duration);
+ if (fwrite (mvhd_data, 1, moovrf->mvhd_size, outf) != moovrf->mvhd_size) {
+ ATOMS_RECOV_OUTPUT_WRITE_ERROR (err);
+ goto fail;
+ }
+ g_free (mvhd_data);
+ mvhd_data = NULL;
+
+ /* write the traks, this is the tough part because we need to update:
+ * - stbl atom
+ * - sizes of atoms from stbl to trak
+ * - trak duration
+ */
+ for (i = 0; i < moovrf->num_traks; i++) {
+ TrakRecovData *trak = &(moovrf->traks_rd[i]);
+ guint trak_data_size;
+ guint32 stbl_new_size;
+ guint32 minf_new_size;
+ guint32 mdia_new_size;
+ guint32 trak_new_size;
+ guint32 size_diff;
+ guint32 duration; /* in moov's timescale */
+
+ /* convert trak duration to moov's duration */
+ duration = gst_util_uint64_scale_round (trak->duration, moovrf->timescale,
+ trak->timescale);
+
+ stbl_children = moov_recov_get_stbl_children_data (moovrf, trak,
+ &stbl_children_size);
+ if (stbl_children == NULL)
+ goto fail;
+
+ /* calc the new size of the atoms from stbl to trak in the atoms tree */
+ stbl_new_size = trak->stsd_size + stbl_children_size + 8;
+ size_diff = stbl_new_size - trak->stbl_size;
+ minf_new_size = trak->minf_size + size_diff;
+ mdia_new_size = trak->mdia_size + size_diff;
+ trak_new_size = trak->trak_size + size_diff;
+
+ if (fseek (moovrf->file, trak->file_offset, SEEK_SET) != 0)
+ goto fail;
+ trak_data_size = trak->post_stsd_offset - trak->file_offset;
+ trak_data = g_malloc (trak_data_size);
+ if (fread (trak_data, 1, trak_data_size, moovrf->file) != trak_data_size) {
+ goto fail;
+ }
+ /* update the size values in those read atoms before writing */
+ GST_WRITE_UINT32_BE (trak_data, trak_new_size);
+ GST_WRITE_UINT32_BE (trak_data + (trak->mdia_file_offset -
+ trak->file_offset), mdia_new_size);
+ GST_WRITE_UINT32_BE (trak_data + (trak->minf_file_offset -
+ trak->file_offset), minf_new_size);
+ GST_WRITE_UINT32_BE (trak_data + (trak->stbl_file_offset -
+ trak->file_offset), stbl_new_size);
+
+ /* update duration values in tkhd and mdhd */
+ GST_WRITE_UINT32_BE (trak_data + (trak->tkhd_file_offset -
+ trak->file_offset) + 28, duration);
+ GST_WRITE_UINT32_BE (trak_data + (trak->mdhd_file_offset -
+ trak->file_offset) + 24, trak->duration);
+
+ if (fwrite (trak_data, 1, trak_data_size, outf) != trak_data_size) {
+ ATOMS_RECOV_OUTPUT_WRITE_ERROR (err);
+ goto fail;
+ }
+ if (fwrite (stbl_children, 1, stbl_children_size, outf) !=
+ stbl_children_size) {
+ ATOMS_RECOV_OUTPUT_WRITE_ERROR (err);
+ goto fail;
+ }
+ g_free (trak_data);
+ trak_data = NULL;
+ g_free (stbl_children);
+ stbl_children = NULL;
+ }
+
+ /* write the mdat */
+ /* write the header first */
+ GST_WRITE_UINT32_BE (auxdata, 1);
+ GST_WRITE_UINT32_LE (auxdata + 4, FOURCC_mdat);
+ GST_WRITE_UINT64_BE (auxdata + 8, mdatrf->mdat_size);
+ if (fwrite (auxdata, 1, 16, outf) != 16) {
+ ATOMS_RECOV_OUTPUT_WRITE_ERROR (err);
+ goto fail;
+ }
+
+ /* now read the mdat data and output to the file */
+ if (fseek (mdatrf->file, mdatrf->mdat_start +
+ (mdatrf->rawfile ? 0 : mdatrf->mdat_header_size), SEEK_SET) != 0)
+ goto fail;
+
+ data = g_malloc (4096);
+ while (!feof (mdatrf->file)) {
+ gint read, write;
+
+ read = fread (data, 1, 4096, mdatrf->file);
+ write = fwrite (data, 1, read, outf);
+
+ if (write != read) {
+ g_set_error (err, ATOMS_RECOV_QUARK, ATOMS_RECOV_ERR_FILE,
+ "Failed to copy data to output file: %s", g_strerror (errno));
+ goto fail;
+ }
+ }
+ g_free (data);
+
+ return TRUE;
+
+fail:
+ g_free (stbl_children);
+ g_free (mvhd_data);
+ g_free (prefix_data);
+ g_free (trak_data);
+ g_free (data);
+ return FALSE;
+}
diff --git a/gst/quicktime/atomsrecovery.h b/gst/quicktime/atomsrecovery.h
new file mode 100644
index 000000000..4dffc48d3
--- /dev/null
+++ b/gst/quicktime/atomsrecovery.h
@@ -0,0 +1,159 @@
+/* Quicktime muxer plugin for GStreamer
+ * Copyright (C) 2010 Thiago Santos <thiago.sousa.santos@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.
+ */
+/*
+ * 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_RECOVERY_H__
+#define __ATOMS_RECOVERY_H__
+
+#include <glib.h>
+#include <string.h>
+#include <stdio.h>
+#include <gst/gst.h>
+
+#include "atoms.h"
+
+/* Version to be incremented each time we decide
+ * to change the file layout */
+#define ATOMS_RECOV_FILE_VERSION 1
+
+#define ATOMS_RECOV_QUARK (g_quark_from_string ("qtmux-atoms-recovery"))
+
+/* gerror error codes */
+#define ATOMS_RECOV_ERR_GENERIC 1
+#define ATOMS_RECOV_ERR_FILE 2
+#define ATOMS_RECOV_ERR_PARSING 3
+#define ATOMS_RECOV_ERR_VERSION 4
+
+/* this struct represents each buffer in a moov file, containing the info
+ * that is placed in the stsd children atoms
+ * Fields should be writen in BE order, and booleans should be writen as
+ * 1byte with 0 for false, anything otherwise */
+#define TRAK_BUFFER_ENTRY_INFO_SIZE 34
+typedef struct
+{
+ guint32 track_id;
+ guint32 nsamples;
+ guint32 delta;
+ guint32 size;
+ guint64 chunk_offset;
+ guint64 pts_offset;
+ gboolean sync;
+ gboolean do_pts;
+} TrakBufferEntryInfo;
+
+typedef struct
+{
+ guint32 trak_id;
+ guint32 duration; /* duration in trak timescale */
+ guint32 timescale; /* trak's timescale */
+
+ guint64 file_offset;
+
+ /* need for later updating duration */
+ guint64 tkhd_file_offset;
+ guint64 mdhd_file_offset;
+
+ /* need these offsets to update size */
+ guint32 trak_size;
+ guint64 mdia_file_offset;
+ guint32 mdia_size;
+ guint64 minf_file_offset;
+ guint32 minf_size;
+ guint64 stbl_file_offset;
+ guint32 stbl_size;
+
+ guint64 post_stsd_offset;
+ guint32 stsd_size;
+
+ /* for storing the samples info */
+ AtomSTBL stbl;
+} TrakRecovData;
+
+typedef struct
+{
+ FILE * file;
+ gboolean rawfile;
+
+ /* results from parsing the input file */
+ guint64 data_size;
+ guint32 mdat_header_size;
+ guint mdat_start;
+
+ guint64 mdat_size;
+} MdatRecovFile;
+
+typedef struct
+{
+ FILE * file;
+ guint32 timescale;
+
+ guint32 mvhd_pos;
+ guint32 mvhd_size;
+ guint32 prefix_size; /* prefix + ftyp total size */
+
+ gint num_traks;
+ TrakRecovData *traks_rd;
+} MoovRecovFile;
+
+gboolean atoms_recov_write_trak_info (FILE * f, AtomTRAK * trak);
+gboolean atoms_recov_write_headers (FILE * f, AtomFTYP * ftyp,
+ GstBuffer * prefix, AtomMOOV * moov,
+ guint32 timescale,
+ guint32 traks_number);
+gboolean atoms_recov_write_trak_samples (FILE * f, AtomTRAK * trak,
+ guint32 nsamples, guint32 delta,
+ guint32 size, guint64 chunk_offset,
+ gboolean sync, gboolean do_pts,
+ gint64 pts_offset);
+
+MdatRecovFile * mdat_recov_file_create (FILE * file, gboolean datafile,
+ GError ** err);
+void mdat_recov_file_free (MdatRecovFile * mrf);
+MoovRecovFile * moov_recov_file_create (FILE * file, GError ** err);
+void moov_recov_file_free (MoovRecovFile * moovrf);
+gboolean moov_recov_parse_buffers (MoovRecovFile * moovrf,
+ MdatRecovFile * mdatrf,
+ GError ** err);
+gboolean moov_recov_write_file (MoovRecovFile * moovrf,
+ MdatRecovFile * mdatrf, FILE * outf,
+ GError ** err);
+
+#endif /* __ATOMS_RECOVERY_H__ */
diff --git a/gst/quicktime/descriptors.c b/gst/quicktime/descriptors.c
new file mode 100644
index 000000000..e7d5a5d42
--- /dev/null
+++ b/gst/quicktime/descriptors.c
@@ -0,0 +1,457 @@
+/* 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 (void)
+{
+ 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 (void)
+{
+ 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);
+}
+
+/*
+ * 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 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_es_descriptor_get_size (desc);
+ 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;
+}
diff --git a/gst/quicktime/descriptors.h b/gst/quicktime/descriptors.h
new file mode 100644
index 000000000..cc633a305
--- /dev/null
+++ b/gst/quicktime/descriptors.h
@@ -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 (void);
+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);
+void desc_dec_specific_info_free (DecoderSpecificInfoDescriptor *dsid);
+void desc_dec_specific_info_alloc_data (DecoderSpecificInfoDescriptor *dsid,
+ guint32 size);
+
+#endif /* __DESCRIPTORS_H__ */
diff --git a/gst/quicktime/fourcc.h b/gst/quicktime/fourcc.h
new file mode 100644
index 000000000..188e20275
--- /dev/null
+++ b/gst/quicktime/fourcc.h
@@ -0,0 +1,243 @@
+/* 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_hmhd GST_MAKE_FOURCC('h','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_aART GST_MAKE_FOURCC('a','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__lyr GST_MAKE_FOURCC(0xa9,'l','y','r')
+#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_VP80 GST_MAKE_FOURCC('V','P','8','0')
+#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')
+#define FOURCC_jp2c GST_MAKE_FOURCC('j','p','2','c')
+#define FOURCC_gama GST_MAKE_FOURCC('g','a','m','a')
+#define FOURCC_tvsh GST_MAKE_FOURCC('t','v','s','h')
+#define FOURCC_tven GST_MAKE_FOURCC('t','v','e','n')
+#define FOURCC_tvsn GST_MAKE_FOURCC('t','v','s','n')
+#define FOURCC_tves GST_MAKE_FOURCC('t','v','e','s')
+#define FOURCC_sonm GST_MAKE_FOURCC('s','o','n','m')
+#define FOURCC_soal GST_MAKE_FOURCC('s','o','a','l')
+#define FOURCC_soar GST_MAKE_FOURCC('s','o','a','r')
+#define FOURCC_soaa GST_MAKE_FOURCC('s','o','a','a')
+#define FOURCC_soco GST_MAKE_FOURCC('s','o','c','o')
+#define FOURCC_sosn GST_MAKE_FOURCC('s','o','s','n')
+#define FOURCC_XMP_ GST_MAKE_FOURCC('X','M','P','_')
+#define FOURCC_uuid GST_MAKE_FOURCC('u','u','i','d')
+
+
+/* SVQ3 fourcc */
+#define FOURCC_SEQH GST_MAKE_FOURCC('S','E','Q','H')
+#define FOURCC_SMI_ GST_MAKE_FOURCC('S','M','I',' ')
+
+/* fragmented mp4 */
+#define FOURCC_mvex GST_MAKE_FOURCC('m','v','e','x')
+#define FOURCC_mehd GST_MAKE_FOURCC('m','e','h','d')
+#define FOURCC_trex GST_MAKE_FOURCC('t','r','e','x')
+#define FOURCC_mfra GST_MAKE_FOURCC('m','f','r','a')
+#define FOURCC_moof GST_MAKE_FOURCC('m','o','o','f')
+#define FOURCC_tfra GST_MAKE_FOURCC('t','f','r','a')
+#define FOURCC_tfhd GST_MAKE_FOURCC('t','f','h','d')
+#define FOURCC_trun GST_MAKE_FOURCC('t','r','u','n')
+#define FOURCC_sdtp GST_MAKE_FOURCC('s','d','t','p')
+#define FOURCC_mfro GST_MAKE_FOURCC('m','f','r','o')
+#define FOURCC_mfhd GST_MAKE_FOURCC('m','f','h','d')
+#define FOURCC_mvhd GST_MAKE_FOURCC('m','v','h','d')
+#define FOURCC_traf GST_MAKE_FOURCC('t','r','a','f')
+
+/* 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')
+#define FOURCC_clsf GST_MAKE_FOURCC('c','l','s','f')
+
+/* For Microsoft Wave formats embedded in quicktime, the FOURCC is
+ 'm', 's', then the 16 bit wave codec id */
+#define MS_WAVE_FOURCC(codecid) GST_MAKE_FOURCC( \
+ 'm', 's', ((codecid)>>8)&0xff, ((codecid)&0xff))
+
+#define FOURCC_owma GST_MAKE_FOURCC('o','w','m','a')
+#define FOURCC_ovc1 GST_MAKE_FOURCC('o','v','c','1')
+
+G_END_DECLS
+
+#endif /* __FOURCC_H__ */
diff --git a/gst/quicktime/ftypcc.h b/gst/quicktime/ftypcc.h
new file mode 100644
index 000000000..3d31b6dd0
--- /dev/null
+++ b/gst/quicktime/ftypcc.h
@@ -0,0 +1,68 @@
+/* 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',' ',' ')
+#define FOURCC_isml GST_MAKE_FOURCC('i','s','m','l')
+#define FOURCC_piff GST_MAKE_FOURCC('p','i','f','f')
+
+G_END_DECLS
+
+#endif /* __FTYP_CC_H__ */
diff --git a/gst/quicktime/gstqtmoovrecover.c b/gst/quicktime/gstqtmoovrecover.c
new file mode 100644
index 000000000..68011dcd6
--- /dev/null
+++ b/gst/quicktime/gstqtmoovrecover.c
@@ -0,0 +1,389 @@
+/* Quicktime muxer plugin for GStreamer
+ * Copyright (C) 2010 Thiago Santos <thiago.sousa.santos@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.
+ */
+/*
+ * 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:gstqtmoovrecover
+ * @short_description: Utility element for recovering unfinished quicktime files
+ *
+ * <refsect2>
+ * <para>
+ * This element recovers quicktime files created with qtmux using the moov recovery feature.
+ * </para>
+ * <title>Example pipelines</title>
+ * <para>
+ * <programlisting>
+ * TODO
+ * </programlisting>
+ * </refsect2>
+ *
+ * Last reviewed on 2010-02-01
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <glib/gstdio.h>
+#include <gst/gst.h>
+
+#include "gstqtmoovrecover.h"
+
+GST_DEBUG_CATEGORY_STATIC (gst_qt_moov_recover_debug);
+#define GST_CAT_DEFAULT gst_qt_moov_recover_debug
+
+/* QTMoovRecover signals and args */
+enum
+{
+ /* FILL ME */
+ LAST_SIGNAL
+};
+
+enum
+{
+ PROP_0,
+ PROP_RECOVERY_INPUT,
+ PROP_BROKEN_INPUT,
+ PROP_FIXED_OUTPUT,
+ PROP_FAST_START_MODE
+};
+
+GST_BOILERPLATE (GstQTMoovRecover, gst_qt_moov_recover, GstPipeline,
+ GST_TYPE_PIPELINE);
+
+/* property functions */
+static void gst_qt_moov_recover_set_property (GObject * object,
+ guint prop_id, const GValue * value, GParamSpec * pspec);
+static void gst_qt_moov_recover_get_property (GObject * object,
+ guint prop_id, GValue * value, GParamSpec * pspec);
+
+static GstStateChangeReturn gst_qt_moov_recover_change_state (GstElement *
+ element, GstStateChange transition);
+
+static void gst_qt_moov_recover_finalize (GObject * object);
+
+static void
+gst_qt_moov_recover_base_init (gpointer g_class)
+{
+ GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
+#if 0
+ GstQTMoovRecoverClass *klass = (GstQTMoovRecoverClass *) g_class;
+#endif
+ gst_element_class_set_details_simple (element_class, "QT Moov Recover",
+ "Util", "Recovers unfinished qtmux files",
+ "Thiago Santos <thiago.sousa.santos@collabora.co.uk>");
+}
+
+static void
+gst_qt_moov_recover_class_init (GstQTMoovRecoverClass * 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_moov_recover_finalize;
+ gobject_class->get_property = gst_qt_moov_recover_get_property;
+ gobject_class->set_property = gst_qt_moov_recover_set_property;
+
+ gstelement_class->change_state = gst_qt_moov_recover_change_state;
+
+ g_object_class_install_property (gobject_class, PROP_FIXED_OUTPUT,
+ g_param_spec_string ("fixed-output",
+ "Path to write the fixed file",
+ "Path to write the fixed file to (used as output)",
+ NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (gobject_class, PROP_BROKEN_INPUT,
+ g_param_spec_string ("broken-input",
+ "Path to broken input file",
+ "Path to broken input file. (If qtmux was on faststart mode, this "
+ "file is the faststart file)", NULL,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (gobject_class, PROP_RECOVERY_INPUT,
+ g_param_spec_string ("recovery-input",
+ "Path to recovery file",
+ "Path to recovery file (used as input)", NULL,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (gobject_class, PROP_FAST_START_MODE,
+ g_param_spec_boolean ("faststart-mode",
+ "If the broken input is from faststart mode",
+ "If the broken input is from faststart mode",
+ FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ GST_DEBUG_CATEGORY_INIT (gst_qt_moov_recover_debug, "qtmoovrecover", 0,
+ "QT Moovie Recover");
+}
+
+static void
+gst_qt_moov_recover_init (GstQTMoovRecover * qtmr,
+ GstQTMoovRecoverClass * qtmr_klass)
+{
+}
+
+static void
+gst_qt_moov_recover_finalize (GObject * object)
+{
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+gst_qt_moov_recover_run (void *data)
+{
+ FILE *moovrec = NULL;
+ FILE *mdatinput = NULL;
+ FILE *output = NULL;
+ MdatRecovFile *mdat_recov = NULL;
+ MoovRecovFile *moov_recov = NULL;
+ GstQTMoovRecover *qtmr = GST_QT_MOOV_RECOVER_CAST (data);
+ GError *err = NULL;
+
+ GST_LOG_OBJECT (qtmr, "Starting task");
+
+ GST_DEBUG_OBJECT (qtmr, "Validating properties");
+ GST_OBJECT_LOCK (qtmr);
+ /* validate properties */
+ if (qtmr->broken_input == NULL) {
+ GST_OBJECT_UNLOCK (qtmr);
+ GST_ELEMENT_ERROR (qtmr, RESOURCE, SETTINGS,
+ ("Please set broken-input property"), (NULL));
+ goto end;
+ }
+ if (qtmr->recovery_input == NULL) {
+ GST_OBJECT_UNLOCK (qtmr);
+ GST_ELEMENT_ERROR (qtmr, RESOURCE, SETTINGS,
+ ("Please set recovery-input property"), (NULL));
+ goto end;
+ }
+ if (qtmr->fixed_output == NULL) {
+ GST_OBJECT_UNLOCK (qtmr);
+ GST_ELEMENT_ERROR (qtmr, RESOURCE, SETTINGS,
+ ("Please set fixed-output property"), (NULL));
+ goto end;
+ }
+
+ GST_DEBUG_OBJECT (qtmr, "Opening input/output files");
+ /* open files */
+ moovrec = g_fopen (qtmr->recovery_input, "rb");
+ if (moovrec == NULL) {
+ GST_OBJECT_UNLOCK (qtmr);
+ GST_ELEMENT_ERROR (qtmr, RESOURCE, OPEN_READ,
+ ("Failed to open recovery-input file"), (NULL));
+ goto end;
+ }
+
+ mdatinput = g_fopen (qtmr->broken_input, "rb");
+ if (mdatinput == NULL) {
+ GST_OBJECT_UNLOCK (qtmr);
+ GST_ELEMENT_ERROR (qtmr, RESOURCE, OPEN_READ,
+ ("Failed to open broken-input file"), (NULL));
+ goto end;
+ }
+ output = g_fopen (qtmr->fixed_output, "wb+");
+ if (output == NULL) {
+ GST_OBJECT_UNLOCK (qtmr);
+ GST_ELEMENT_ERROR (qtmr, RESOURCE, OPEN_READ_WRITE,
+ ("Failed to open fixed-output file"), (NULL));
+ goto end;
+ }
+ GST_OBJECT_UNLOCK (qtmr);
+
+ GST_DEBUG_OBJECT (qtmr, "Parsing input files");
+ /* now create our structures */
+ mdat_recov = mdat_recov_file_create (mdatinput, qtmr->faststart_mode, &err);
+ mdatinput = NULL;
+ if (mdat_recov == NULL) {
+ GST_ELEMENT_ERROR (qtmr, RESOURCE, FAILED,
+ ("Broken file could not be parsed correctly"), (NULL));
+ goto end;
+ }
+ moov_recov = moov_recov_file_create (moovrec, &err);
+ moovrec = NULL;
+ if (moov_recov == NULL) {
+ GST_ELEMENT_ERROR (qtmr, RESOURCE, FAILED,
+ ("Recovery file could not be parsed correctly"), (NULL));
+ goto end;
+ }
+
+ /* now parse the buffers data from moovrec */
+ if (!moov_recov_parse_buffers (moov_recov, mdat_recov, &err)) {
+ goto end;
+ }
+
+ GST_DEBUG_OBJECT (qtmr, "Writing fixed file to output");
+ if (!moov_recov_write_file (moov_recov, mdat_recov, output, &err)) {
+ goto end;
+ }
+
+ /* here means success */
+ GST_DEBUG_OBJECT (qtmr, "Finished successfully, posting EOS");
+ gst_element_post_message (GST_ELEMENT_CAST (qtmr),
+ gst_message_new_eos (GST_OBJECT_CAST (qtmr)));
+
+end:
+ GST_LOG_OBJECT (qtmr, "Finalizing task");
+ if (err) {
+ GST_ELEMENT_ERROR (qtmr, RESOURCE, FAILED, ("%s", err->message), (NULL));
+ g_error_free (err);
+ }
+
+ if (moov_recov)
+ moov_recov_file_free (moov_recov);
+ if (moovrec)
+ fclose (moovrec);
+
+ if (mdat_recov)
+ mdat_recov_file_free (mdat_recov);
+ if (mdatinput)
+ fclose (mdatinput);
+
+ if (output)
+ fclose (output);
+ GST_LOG_OBJECT (qtmr, "Leaving task");
+ gst_task_stop (qtmr->task);
+}
+
+static void
+gst_qt_moov_recover_get_property (GObject * object,
+ guint prop_id, GValue * value, GParamSpec * pspec)
+{
+ GstQTMoovRecover *qtmr = GST_QT_MOOV_RECOVER_CAST (object);
+
+ GST_OBJECT_LOCK (qtmr);
+ switch (prop_id) {
+ case PROP_FAST_START_MODE:
+ g_value_set_boolean (value, qtmr->faststart_mode);
+ break;
+ case PROP_BROKEN_INPUT:
+ g_value_set_string (value, qtmr->broken_input);
+ break;
+ case PROP_RECOVERY_INPUT:
+ g_value_set_string (value, qtmr->recovery_input);
+ break;
+ case PROP_FIXED_OUTPUT:
+ g_value_set_string (value, qtmr->fixed_output);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+ GST_OBJECT_UNLOCK (qtmr);
+}
+
+static void
+gst_qt_moov_recover_set_property (GObject * object,
+ guint prop_id, const GValue * value, GParamSpec * pspec)
+{
+ GstQTMoovRecover *qtmr = GST_QT_MOOV_RECOVER_CAST (object);
+
+ GST_OBJECT_LOCK (qtmr);
+ switch (prop_id) {
+ case PROP_FAST_START_MODE:
+ qtmr->faststart_mode = g_value_get_boolean (value);
+ break;
+ case PROP_BROKEN_INPUT:
+ g_free (qtmr->broken_input);
+ qtmr->broken_input = g_value_dup_string (value);
+ break;
+ case PROP_RECOVERY_INPUT:
+ g_free (qtmr->recovery_input);
+ qtmr->recovery_input = g_value_dup_string (value);
+ break;
+ case PROP_FIXED_OUTPUT:
+ g_free (qtmr->fixed_output);
+ qtmr->fixed_output = g_value_dup_string (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+ GST_OBJECT_UNLOCK (qtmr);
+}
+
+static GstStateChangeReturn
+gst_qt_moov_recover_change_state (GstElement * element,
+ GstStateChange transition)
+{
+ GstStateChangeReturn ret;
+ GstQTMoovRecover *qtmr = GST_QT_MOOV_RECOVER_CAST (element);
+
+ switch (transition) {
+ case GST_STATE_CHANGE_NULL_TO_READY:
+ qtmr->task = gst_task_create (gst_qt_moov_recover_run, qtmr);
+ g_static_rec_mutex_init (&qtmr->task_mutex);
+ gst_task_set_lock (qtmr->task, &qtmr->task_mutex);
+ break;
+ case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
+ gst_task_start (qtmr->task);
+ break;
+ default:
+ break;
+ }
+
+ ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
+
+ switch (transition) {
+ case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
+ gst_task_stop (qtmr->task);
+ gst_task_join (qtmr->task);
+ break;
+ case GST_STATE_CHANGE_READY_TO_NULL:
+ g_assert (gst_task_get_state (qtmr->task) == GST_TASK_STOPPED);
+ gst_object_unref (qtmr->task);
+ qtmr->task = NULL;
+ g_static_rec_mutex_free (&qtmr->task_mutex);
+ break;
+ default:
+ break;
+ }
+ return ret;
+}
+
+
+gboolean
+gst_qt_moov_recover_register (GstPlugin * plugin)
+{
+ return gst_element_register (plugin, "qtmoovrecover", GST_RANK_NONE,
+ GST_TYPE_QT_MOOV_RECOVER);
+}
diff --git a/gst/quicktime/gstqtmoovrecover.h b/gst/quicktime/gstqtmoovrecover.h
new file mode 100644
index 000000000..15eac847b
--- /dev/null
+++ b/gst/quicktime/gstqtmoovrecover.h
@@ -0,0 +1,88 @@
+/* Quicktime muxer plugin for GStreamer
+ * Copyright (C) 2010 Thiago Santos <thiago.sousa.santos@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.
+ */
+/*
+ * 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_MOOV_RECOVER_H__
+#define __GST_QT_MOOV_RECOVER_H__
+
+#include <gst/gst.h>
+
+#include "atoms.h"
+#include "atomsrecovery.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_QT_MOOV_RECOVER (gst_qt_moov_recover_get_type())
+#define GST_QT_MOOV_RECOVER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_QT_MOOV_RECOVER, GstQTMoovRecover))
+#define GST_QT_MOOV_RECOVER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_QT_MOOV_RECOVER, GstQTMoovRecover))
+#define GST_IS_QT_MOOV_RECOVER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_QT_MOOV_RECOVER))
+#define GST_IS_QT_MOOV_RECOVER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_QT_MOOV_RECOVER))
+#define GST_QT_MOOV_RECOVER_CAST(obj) ((GstQTMoovRecover*)(obj))
+
+
+typedef struct _GstQTMoovRecover GstQTMoovRecover;
+typedef struct _GstQTMoovRecoverClass GstQTMoovRecoverClass;
+
+struct _GstQTMoovRecover
+{
+ GstPipeline pipeline;
+
+ GstTask *task;
+ GStaticRecMutex task_mutex;
+
+ /* properties */
+ gboolean faststart_mode;
+ gchar *recovery_input;
+ gchar *fixed_output;
+ gchar *broken_input;
+};
+
+struct _GstQTMoovRecoverClass
+{
+ GstPipelineClass parent_class;
+};
+
+GType gst_qt_moov_recover_get_type (void);
+gboolean gst_qt_moov_recover_register (GstPlugin * plugin);
+
+G_END_DECLS
+
+#endif /* __GST_QT_MOOV_RECOVER_H__ */
diff --git a/gst/quicktime/gstqtmux.c b/gst/quicktime/gstqtmux.c
new file mode 100644
index 000000000..0bfbd97f6
--- /dev/null
+++ b/gst/quicktime/gstqtmux.c
@@ -0,0 +1,3525 @@
+/* Quicktime muxer plugin for GStreamer
+ * Copyright (C) 2008-2010 Thiago Santos <thiagoss@embedded.ufcg.edu.br>
+ * Copyright (C) 2008 Mark Nauwelaerts <mnauw@users.sf.net>
+ * Copyright (C) 2010 Nokia Corporation. All rights reserved.
+ * Contact: Stefan Kost <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.
+ */
+/*
+ * 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:element-qtmux
+ * @short_description: Muxer for quicktime(.mov) files
+ *
+ * This element merges streams (audio and video) into QuickTime(.mov) files.
+ *
+ * The following background intends to explain why various similar muxers
+ * are present in this plugin.
+ *
+ * The <ulink url="http://www.apple.com/quicktime/resources/qtfileformat.pdf">
+ * QuickTime file format specification</ulink> served as basis for the MP4 file
+ * format specification (mp4mux), and as such the QuickTime file structure is
+ * nearly identical to the so-called ISO Base Media file format defined in
+ * ISO 14496-12 (except for some media specific parts).
+ * In turn, the latter ISO Base Media format was further specialized as a
+ * Motion JPEG-2000 file format in ISO 15444-3 (mj2mux)
+ * and in various 3GPP(2) specs (gppmux).
+ * The fragmented file features defined (only) in ISO Base Media are used by
+ * ISMV files making up (a.o.) Smooth Streaming (ismlmux).
+ *
+ * A few properties (<link linkend="GstQTMux--movie-timescale">movie-timescale</link>,
+ * <link linkend="GstQTMux--trak-timescale">trak-timescale</link>) allow adjusting
+ * some technical parameters, which might be useful in (rare) cases to resolve
+ * compatibility issues in some situations.
+ *
+ * Some other properties influence the result more fundamentally.
+ * A typical mov/mp4 file's metadata (aka moov) is located at the end of the file,
+ * somewhat contrary to this usually being called "the header".
+ * However, a <link linkend="GstQTMux--faststart">faststart</link> file will
+ * (with some effort) arrange this to be located near start of the file,
+ * which then allows it e.g. to be played while downloading.
+ * Alternatively, rather than having one chunk of metadata at start (or end),
+ * there can be some metadata at start and most of the other data can be spread
+ * out into fragments of <link linkend="GstQTMux--fragment-duration">fragment-duration</link>.
+ * If such fragmented layout is intended for streaming purposes, then
+ * <link linkend="GstQTMux--streamable">streamable</link> allows foregoing to add
+ * index metadata (at the end of file).
+ *
+ * <link linkend="GstQTMux--dts-method">dts-method</link> allows selecting a
+ * method for managing input timestamps (stay tuned for 0.11 to have this
+ * automagically settled). The default delta/duration method should handle nice
+ * (aka perfect streams) just fine, but may experience problems otherwise
+ * (e.g. input stream with re-ordered B-frames and/or with frame dropping).
+ * The re-ordering approach re-assigns incoming timestamps in ascending order
+ * to incoming buffers and offers an alternative in such cases. In cases where
+ * that might fail, the remaining method can be tried, which is exact and
+ * according to specs, but might experience playback on not so spec-wise players.
+ * Note that this latter approach also requires one to enable
+ * <link linkend="GstQTMux--presentation-timestamp">presentation-timestamp</link>.
+ *
+ * <refsect2>
+ * <title>Example pipelines</title>
+ * |[
+ * gst-launch v4l2src num-buffers=500 ! video/x-raw-yuv,width=320,height=240 ! ffmpegcolorspace ! qtmux ! filesink location=video.mov
+ * ]|
+ * Records a video stream captured from a v4l2 device and muxes it into a qt file.
+ * </refsect2>
+ *
+ * Last reviewed on 2010-12-03
+ */
+
+/*
+ * 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 <gst/tag/xmpwriter.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 _MSC_VER
+#define ftruncate g_win32_ftruncate
+#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
+
+enum
+{
+ DTS_METHOD_DD,
+ DTS_METHOD_REORDER,
+ DTS_METHOD_ASC
+};
+
+static GType
+gst_qt_mux_dts_method_get_type (void)
+{
+ static GType gst_qt_mux_dts_method = 0;
+
+ if (!gst_qt_mux_dts_method) {
+ static const GEnumValue dts_methods[] = {
+ {DTS_METHOD_DD, "delta/duration", "dd"},
+ {DTS_METHOD_REORDER, "reorder", "reorder"},
+ {DTS_METHOD_ASC, "ascending", "asc"},
+ {0, NULL, NULL},
+ };
+
+ gst_qt_mux_dts_method =
+ g_enum_register_static ("GstQTMuxDtsMethods", dts_methods);
+ }
+
+ return gst_qt_mux_dts_method;
+}
+
+#define GST_TYPE_QT_MUX_DTS_METHOD \
+ (gst_qt_mux_dts_method_get_type ())
+
+/* QTMux signals and args */
+enum
+{
+ /* FILL ME */
+ LAST_SIGNAL
+};
+
+enum
+{
+ PROP_0,
+ PROP_MOVIE_TIMESCALE,
+ PROP_TRAK_TIMESCALE,
+ PROP_FAST_START,
+ PROP_FAST_START_TEMP_FILE,
+ PROP_MOOV_RECOV_FILE,
+ PROP_FRAGMENT_DURATION,
+ PROP_STREAMABLE,
+ PROP_DTS_METHOD,
+ PROP_DO_CTTS,
+};
+
+/* some spare for header size as well */
+#define MDAT_LARGE_FILE_LIMIT ((guint64) 1024 * 1024 * 1024 * 2)
+#define MAX_TOLERATED_LATENESS (GST_SECOND / 10)
+
+#define DEFAULT_MOVIE_TIMESCALE 1000
+#define DEFAULT_TRAK_TIMESCALE 0
+#define DEFAULT_DO_CTTS TRUE
+#define DEFAULT_FAST_START FALSE
+#define DEFAULT_FAST_START_TEMP_FILE NULL
+#define DEFAULT_MOOV_RECOV_FILE NULL
+#define DEFAULT_FRAGMENT_DURATION 0
+#define DEFAULT_STREAMABLE FALSE
+#define DEFAULT_DTS_METHOD DTS_METHOD_REORDER
+
+
+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;
+ GstPadTemplate *videosinktempl, *audiosinktempl, *srctempl;
+ gchar *longname, *description;
+
+ 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 */
+ longname = g_strdup_printf ("%s Muxer", params->prop->long_name);
+ description = g_strdup_printf ("Multiplex audio and video into a %s file",
+ params->prop->long_name);
+ gst_element_class_set_details_simple (element_class, longname,
+ "Codec/Muxer", description,
+ "Thiago Sousa Santos <thiagoss@embedded.ufcg.edu.br>");
+ g_free (longname);
+ g_free (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_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_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (gobject_class, PROP_TRAK_TIMESCALE,
+ g_param_spec_uint ("trak-timescale", "Track timescale",
+ "Timescale to use for the tracks (units per second, 0 is automatic)",
+ 0, G_MAXUINT32, DEFAULT_TRAK_TIMESCALE,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
+ 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)", DEFAULT_DO_CTTS,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (gobject_class, PROP_DTS_METHOD,
+ g_param_spec_enum ("dts-method", "dts-method",
+ "Method to determine DTS time",
+ GST_TYPE_QT_MUX_DTS_METHOD, DEFAULT_DTS_METHOD,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (gobject_class, PROP_FAST_START,
+ g_param_spec_boolean ("faststart", "Format file to faststart",
+ "If the file should be formatted for faststart (headers first)",
+ DEFAULT_FAST_START, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ 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 | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (gobject_class, PROP_MOOV_RECOV_FILE,
+ g_param_spec_string ("moov-recovery-file",
+ "File to store data for posterior moov atom recovery",
+ "File to be used to store "
+ "data for moov atom making movie file recovery possible in case "
+ "of a crash during muxing. Null for disabled. (Experimental)",
+ DEFAULT_MOOV_RECOV_FILE,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (gobject_class, PROP_FRAGMENT_DURATION,
+ g_param_spec_uint ("fragment-duration", "Fragment duration",
+ "Fragment durations in ms (produce a fragmented file if > 0)",
+ 0, G_MAXUINT32, klass->format == GST_QT_MUX_FORMAT_ISML ?
+ 2000 : DEFAULT_FRAGMENT_DURATION,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (gobject_class, PROP_STREAMABLE,
+ g_param_spec_boolean ("streamable", "Streamable",
+ "If set to true, the output should be as if it is to be streamed "
+ "and hence no indexes written or duration written.",
+ DEFAULT_STREAMABLE,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
+
+ 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)
+{
+ gint i;
+
+ qtpad->fourcc = 0;
+ qtpad->is_out_of_order = FALSE;
+ qtpad->have_dts = FALSE;
+ qtpad->sample_size = 0;
+ qtpad->sync = FALSE;
+ qtpad->last_dts = 0;
+ qtpad->first_ts = GST_CLOCK_TIME_NONE;
+ qtpad->prepare_buf_func = NULL;
+ qtpad->avg_bitrate = 0;
+ qtpad->max_bitrate = 0;
+ qtpad->ts_n_entries = 0;
+
+ qtpad->buf_head = 0;
+ qtpad->buf_tail = 0;
+ for (i = 0; i < G_N_ELEMENTS (qtpad->buf_entries); i++) {
+ if (qtpad->buf_entries[i]) {
+ gst_buffer_unref (qtpad->buf_entries[i]);
+ qtpad->buf_entries[i] = NULL;
+ }
+ }
+
+ if (qtpad->last_buf)
+ gst_buffer_replace (&qtpad->last_buf, NULL);
+
+ /* reference owned elsewhere */
+ qtpad->trak = NULL;
+
+ if (qtpad->traf) {
+ atom_traf_free (qtpad->traf);
+ qtpad->traf = NULL;
+ }
+ atom_array_clear (&qtpad->fragment_buffers);
+
+ /* reference owned elsewhere */
+ qtpad->tfra = 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;
+ qtmux->video_pads = 0;
+ qtmux->audio_pads = 0;
+ qtmux->fragment_sequence = 0;
+
+ if (qtmux->ftyp) {
+ atom_ftyp_free (qtmux->ftyp);
+ qtmux->ftyp = NULL;
+ }
+ if (qtmux->moov) {
+ atom_moov_free (qtmux->moov);
+ qtmux->moov = NULL;
+ }
+ if (qtmux->mfra) {
+ atom_mfra_free (qtmux->mfra);
+ qtmux->mfra = NULL;
+ }
+ if (qtmux->fast_start_file) {
+ fclose (qtmux->fast_start_file);
+ g_remove (qtmux->fast_start_file_path);
+ qtmux->fast_start_file = NULL;
+ }
+ if (qtmux->moov_recov_file) {
+ fclose (qtmux->moov_recov_file);
+ qtmux->moov_recov_file = NULL;
+ }
+ for (walk = qtmux->extra_atoms; walk; walk = g_slist_next (walk)) {
+ AtomInfo *ainfo = (AtomInfo *) walk->data;
+ ainfo->free_func (ainfo->atom);
+ g_free (ainfo);
+ }
+ g_slist_free (qtmux->extra_atoms);
+ qtmux->extra_atoms = NULL;
+
+ GST_OBJECT_LOCK (qtmux);
+ gst_tag_setter_reset_tags (GST_TAG_SETTER (qtmux));
+ GST_OBJECT_UNLOCK (qtmux);
+
+ /* reset pad data */
+ for (walk = qtmux->sinkpads; 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->sinkpads; 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;
+
+ templ = gst_element_class_get_pad_template (klass, "src");
+ qtmux->srcpad = gst_pad_new_from_template (templ, "src");
+ gst_pad_use_fixed_caps (qtmux->srcpad);
+ gst_element_add_pad (GST_ELEMENT (qtmux), qtmux->srcpad);
+
+ qtmux->sinkpads = NULL;
+ 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);
+
+ g_free (qtmux->fast_start_file_path);
+ g_free (qtmux->moov_recov_file_path);
+
+ atoms_context_free (qtmux->context);
+ gst_object_unref (qtmux->collect);
+
+ g_slist_free (qtmux->sinkpads);
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static GstBuffer *
+gst_qt_mux_prepare_jpc_buffer (GstQTPad * qtpad, GstBuffer * buf,
+ GstQTMux * qtmux)
+{
+ GstBuffer *newbuf;
+
+ GST_LOG_OBJECT (qtmux, "Preparing jpc buffer");
+
+ if (buf == NULL)
+ return NULL;
+
+ newbuf = gst_buffer_new_and_alloc (GST_BUFFER_SIZE (buf) + 8);
+ gst_buffer_copy_metadata (newbuf, buf, GST_BUFFER_COPY_ALL);
+
+ GST_WRITE_UINT32_BE (GST_BUFFER_DATA (newbuf), GST_BUFFER_SIZE (newbuf));
+ GST_WRITE_UINT32_LE (GST_BUFFER_DATA (newbuf) + 4, FOURCC_jp2c);
+
+ memcpy (GST_BUFFER_DATA (newbuf) + 8, GST_BUFFER_DATA (buf),
+ GST_BUFFER_SIZE (buf));
+ gst_buffer_unref (buf);
+
+ return newbuf;
+}
+
+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;
+ }
+ case G_TYPE_UINT:
+ {
+ guint value = 0;
+ if (tag2) {
+ /* paired unsigned integers */
+ guint count = 0;
+
+ 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));
+ } else {
+ /* unpaired unsigned integers */
+ if (!gst_tag_list_get_uint (list, tag, &value))
+ break;
+ GST_DEBUG_OBJECT (qtmux, "Adding tag %" GST_FOURCC_FORMAT " -> %u",
+ GST_FOURCC_ARGS (fourcc), value);
+ atom_moov_add_uint_tag (qtmux->moov, fourcc, 1, value);
+ }
+ 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);
+ g_free (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);
+ g_free (keywords);
+
+ 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);
+}
+
+static gboolean
+gst_qt_mux_parse_classification_string (GstQTMux * qtmux, const gchar * input,
+ guint32 * p_fourcc, guint16 * p_table, gchar ** p_content)
+{
+ guint32 fourcc;
+ gint table;
+ gint size;
+ const gchar *data;
+
+ data = input;
+ size = strlen (input);
+
+ if (size < 4 + 3 + 1 + 1 + 1) {
+ /* at least the minimum xxxx://y/z */
+ GST_WARNING_OBJECT (qtmux, "Classification tag input (%s) too short, "
+ "ignoring", input);
+ return FALSE;
+ }
+
+ /* read the fourcc */
+ memcpy (&fourcc, data, 4);
+ size -= 4;
+ data += 4;
+
+ if (strncmp (data, "://", 3) != 0) {
+ goto mismatch;
+ }
+ data += 3;
+ size -= 3;
+
+ /* read the table number */
+ if (sscanf (data, "%d", &table) != 1) {
+ goto mismatch;
+ }
+ if (table < 0) {
+ GST_WARNING_OBJECT (qtmux, "Invalid table number in classification tag (%d)"
+ ", table numbers should be positive, ignoring tag", table);
+ return FALSE;
+ }
+
+ /* find the next / */
+ while (size > 0 && data[0] != '/') {
+ data += 1;
+ size -= 1;
+ }
+ if (size == 0) {
+ goto mismatch;
+ }
+ g_assert (data[0] == '/');
+
+ /* skip the '/' */
+ data += 1;
+ size -= 1;
+ if (size == 0) {
+ goto mismatch;
+ }
+
+ /* read up the rest of the string */
+ *p_content = g_strdup (data);
+ *p_table = (guint16) table;
+ *p_fourcc = fourcc;
+ return TRUE;
+
+mismatch:
+ {
+ GST_WARNING_OBJECT (qtmux, "Ignoring classification tag as "
+ "input (%s) didn't match the expected entitycode://table/content",
+ input);
+ return FALSE;
+ }
+}
+
+static void
+gst_qt_mux_add_3gp_classification (GstQTMux * qtmux, const GstTagList * list,
+ const char *tag, const char *tag2, guint32 fourcc)
+{
+ gchar *clsf_data = NULL;
+ gint size = 0;
+ guint32 entity = 0;
+ guint16 table = 0;
+ gchar *content = NULL;
+ guint8 *data;
+
+ g_return_if_fail (strcmp (tag, GST_TAG_3GP_CLASSIFICATION) == 0);
+
+ if (!gst_tag_list_get_string (list, tag, &clsf_data) || !clsf_data)
+ return;
+
+ GST_DEBUG_OBJECT (qtmux, "Adding tag %" GST_FOURCC_FORMAT " -> %s",
+ GST_FOURCC_ARGS (fourcc), clsf_data);
+
+ /* parse the string, format is:
+ * entityfourcc://table/content
+ */
+ gst_qt_mux_parse_classification_string (qtmux, clsf_data, &entity, &table,
+ &content);
+ g_free (clsf_data);
+ /* +1 for the \0 */
+ size = strlen (content) + 1;
+
+ /* now we have everything, build the atom
+ * atom description is at 3GPP TS 26.244 V8.2.0 (2009-09) */
+ data = g_malloc (4 + 2 + 2 + size);
+ GST_WRITE_UINT32_LE (data, entity);
+ GST_WRITE_UINT16_BE (data + 4, (guint16) table);
+ GST_WRITE_UINT16_BE (data + 6, 0);
+ memcpy (data + 8, content, size);
+ g_free (content);
+
+ atom_moov_add_3gp_tag (qtmux->moov, fourcc, data, 4 + 2 + 2 + size);
+ g_free (data);
+}
+
+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_soal, GST_TAG_ALBUM_SORTNAME, NULL, gst_qt_mux_add_mp4_tag},
+ {FOURCC__ART, GST_TAG_ARTIST, NULL, gst_qt_mux_add_mp4_tag},
+ {FOURCC_soar, GST_TAG_ARTIST_SORTNAME, NULL, gst_qt_mux_add_mp4_tag},
+ {FOURCC_aART, GST_TAG_ALBUM_ARTIST, NULL, gst_qt_mux_add_mp4_tag},
+ {FOURCC_soaa, GST_TAG_ALBUM_ARTIST_SORTNAME, 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_soco, GST_TAG_COMPOSER_SORTNAME, NULL, gst_qt_mux_add_mp4_tag},
+ {FOURCC_tvsh, GST_TAG_SHOW_NAME, NULL, gst_qt_mux_add_mp4_tag},
+ {FOURCC_sosn, GST_TAG_SHOW_SORTNAME, NULL, gst_qt_mux_add_mp4_tag},
+ {FOURCC_tvsn, GST_TAG_SHOW_SEASON_NUMBER, NULL, gst_qt_mux_add_mp4_tag},
+ {FOURCC_tves, GST_TAG_SHOW_EPISODE_NUMBER, 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_sonm, GST_TAG_TITLE_SORTNAME, NULL, gst_qt_mux_add_mp4_tag},
+ {FOURCC_perf, GST_TAG_PERFORMER, NULL, gst_qt_mux_add_mp4_tag},
+ {FOURCC__grp, GST_TAG_GROUPING, NULL, gst_qt_mux_add_mp4_tag},
+ {FOURCC__des, GST_TAG_DESCRIPTION, NULL, gst_qt_mux_add_mp4_tag},
+ {FOURCC__lyr, GST_TAG_LYRICS, 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},
+ {FOURCC_clsf, GST_TAG_3GP_CLASSIFICATION, NULL,
+ gst_qt_mux_add_3gp_classification},
+ {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_xmp_tags (GstQTMux * qtmux, const GstTagList * list)
+{
+ GstQTMuxClass *qtmux_klass = (GstQTMuxClass *) (G_OBJECT_GET_CLASS (qtmux));
+ GstBuffer *xmp = NULL;
+
+ /* adobe specs only have 'quicktime' and 'mp4',
+ * but I guess we can extrapolate to gpp.
+ * Keep mj2 out for now as we don't add any tags for it yet.
+ * If you have further info about xmp on these formats, please share */
+ if (qtmux_klass->format == GST_QT_MUX_FORMAT_MJ2)
+ return;
+
+ GST_DEBUG_OBJECT (qtmux, "Adding xmp tags");
+
+ if (qtmux_klass->format == GST_QT_MUX_FORMAT_QT) {
+ xmp = gst_tag_xmp_writer_tag_list_to_xmp_buffer (GST_TAG_XMP_WRITER (qtmux),
+ list, TRUE);
+ if (xmp)
+ atom_moov_add_xmp_tags (qtmux->moov, xmp);
+ } else {
+ AtomInfo *ainfo;
+ /* for isom/mp4, it is a top level uuid atom */
+ xmp = gst_tag_xmp_writer_tag_list_to_xmp_buffer (GST_TAG_XMP_WRITER (qtmux),
+ list, TRUE);
+ if (xmp) {
+ ainfo = build_uuid_xmp_atom (xmp);
+ if (ainfo) {
+ qtmux->extra_atoms = g_slist_prepend (qtmux->extra_atoms, ainfo);
+ }
+ }
+ }
+ if (xmp)
+ gst_buffer_unref (xmp);
+}
+
+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;
+
+ GST_OBJECT_LOCK (qtmux);
+ tags = gst_tag_setter_get_tag_list (GST_TAG_SETTER (qtmux));
+ GST_OBJECT_UNLOCK (qtmux);
+
+ GST_LOG_OBJECT (qtmux, "tags: %" GST_PTR_FORMAT, tags);
+
+ if (tags && !gst_tag_list_is_empty (tags)) {
+ GstTagList *copy = gst_tag_list_copy (tags);
+
+ GST_DEBUG_OBJECT (qtmux, "Removing bogus tags");
+ gst_tag_list_remove_tag (copy, GST_TAG_VIDEO_CODEC);
+ gst_tag_list_remove_tag (copy, GST_TAG_AUDIO_CODEC);
+ gst_tag_list_remove_tag (copy, GST_TAG_CONTAINER_FORMAT);
+
+ GST_DEBUG_OBJECT (qtmux, "Formatting tags");
+ gst_qt_mux_add_metadata_tags (qtmux, copy);
+ gst_qt_mux_add_xmp_tags (qtmux, copy);
+ gst_tag_list_free (copy);
+ } else {
+ GST_DEBUG_OBJECT (qtmux, "No tags received");
+ }
+}
+
+static inline GstBuffer *
+_gst_buffer_new_take_data (guint8 * data, guint size)
+{
+ GstBuffer *buf;
+
+ buf = gst_buffer_new ();
+ GST_BUFFER_DATA (buf) = GST_BUFFER_MALLOCDATA (buf) = data;
+ GST_BUFFER_SIZE (buf) = size;
+
+ return buf;
+}
+
+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");
+
+ buf = gst_buffer_make_metadata_writable (buf);
+ 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 gboolean
+gst_qt_mux_seek_to_beginning (FILE * f)
+{
+#ifdef HAVE_FSEEKO
+ if (fseeko (f, (off_t) 0, SEEK_SET) != 0)
+ return FALSE;
+#elif defined (G_OS_UNIX) || defined (G_OS_WIN32)
+ if (lseek (fileno (f), (off_t) 0, SEEK_SET) == (off_t) - 1)
+ return FALSE;
+#else
+ if (fseek (f, (long) 0, SEEK_SET) != 0)
+ return FALSE;
+#endif
+ return TRUE;
+}
+
+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;
+
+ if (!gst_qt_mux_seek_to_beginning (qtmux->fast_start_file))
+ goto seek_failed;
+
+ /* 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);
+
+ if (ftruncate (fileno (qtmux->fast_start_file), 0))
+ goto seek_failed;
+ if (!gst_qt_mux_seek_to_beginning (qtmux->fast_start_file))
+ goto seek_failed;
+
+ return ret;
+
+ /* ERRORS */
+flush_failed:
+ {
+ GST_ELEMENT_ERROR (qtmux, RESOURCE, WRITE,
+ ("Failed to flush temporary file"), GST_ERROR_SYSTEM);
+ ret = GST_FLOW_ERROR;
+ goto fail;
+ }
+seek_failed:
+ {
+ GST_ELEMENT_ERROR (qtmux, RESOURCE, SEEK,
+ ("Failed to seek temporary file"), GST_ERROR_SYSTEM);
+ ret = GST_FLOW_ERROR;
+ goto fail;
+ }
+fail:
+ {
+ /* clear descriptor so we don't remove temp file later on,
+ * might be possible to recover */
+ fclose (qtmux->fast_start_file);
+ qtmux->fast_start_file = NULL;
+ return ret;
+ }
+}
+
+/*
+ * 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_take_data (data, 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 mdat"));
+ 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_take_data (data, 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 void
+gst_qt_mux_prepare_ftyp (GstQTMux * qtmux, AtomFTYP ** p_ftyp,
+ GstBuffer ** p_prefix)
+{
+ GstQTMuxClass *qtmux_klass = (GstQTMuxClass *) (G_OBJECT_GET_CLASS (qtmux));
+ guint32 major, version;
+ GList *comp;
+ GstBuffer *prefix = NULL;
+ AtomFTYP *ftyp = NULL;
+
+ GST_DEBUG_OBJECT (qtmux, "Preparing ftyp and possible prefix atom");
+
+ /* init and send context and ftyp based on current property state */
+ gst_qt_mux_map_format_to_header (qtmux_klass->format, &prefix, &major,
+ &version, &comp, qtmux->moov, qtmux->longest_chunk,
+ qtmux->fast_start_file != NULL);
+ ftyp = atom_ftyp_new (qtmux->context, major, version, comp);
+ if (comp)
+ g_list_free (comp);
+ if (prefix) {
+ if (p_prefix)
+ *p_prefix = prefix;
+ else
+ gst_buffer_unref (prefix);
+ }
+ *p_ftyp = ftyp;
+}
+
+static GstFlowReturn
+gst_qt_mux_prepare_and_send_ftyp (GstQTMux * qtmux)
+{
+ GstFlowReturn ret = GST_FLOW_OK;
+ GstBuffer *prefix = NULL;
+
+ 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);
+ qtmux->ftyp = NULL;
+ }
+ gst_qt_mux_prepare_ftyp (qtmux, &qtmux->ftyp, &prefix);
+ 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 void
+gst_qt_mux_set_header_on_caps (GstQTMux * mux, GstBuffer * buf)
+{
+ GstStructure *structure;
+ GValue array = { 0 };
+ GValue value = { 0 };
+ GstCaps *caps = GST_PAD_CAPS (mux->srcpad);
+
+ caps = gst_caps_copy (GST_PAD_CAPS (mux->srcpad));
+ structure = gst_caps_get_structure (caps, 0);
+
+ g_value_init (&array, GST_TYPE_ARRAY);
+
+ GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_IN_CAPS);
+ g_value_init (&value, GST_TYPE_BUFFER);
+ gst_value_take_buffer (&value, gst_buffer_ref (buf));
+ gst_value_array_append_value (&array, &value);
+ g_value_unset (&value);
+
+ gst_structure_set_value (structure, "streamheader", &array);
+ g_value_unset (&array);
+ gst_pad_set_caps (mux->srcpad, caps);
+ gst_caps_unref (caps);
+}
+
+static void
+gst_qt_mux_configure_moov (GstQTMux * qtmux, guint32 * _timescale)
+{
+ gboolean fragmented;
+ guint32 timescale;
+
+ GST_OBJECT_LOCK (qtmux);
+ timescale = qtmux->timescale;
+ fragmented = qtmux->fragment_sequence > 0;
+ 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, "Updating timescale to %" G_GUINT32_FORMAT,
+ timescale);
+ atom_moov_update_timescale (qtmux->moov, timescale);
+ atom_moov_set_fragmented (qtmux->moov, fragmented);
+
+ atom_moov_update_duration (qtmux->moov);
+
+ if (_timescale)
+ *_timescale = timescale;
+}
+
+static GstFlowReturn
+gst_qt_mux_send_moov (GstQTMux * qtmux, guint64 * _offset, gboolean mind_fast)
+{
+ guint64 offset = 0, size = 0;
+ guint8 *data;
+ GstBuffer *buf;
+ GstFlowReturn ret = GST_FLOW_OK;
+
+ /* serialize moov */
+ offset = size = 0;
+ data = NULL;
+ GST_LOG_OBJECT (qtmux, "Copying movie header into buffer");
+ if (!atom_moov_copy_data (qtmux->moov, &data, &size, &offset))
+ goto serialize_error;
+
+ buf = _gst_buffer_new_take_data (data, offset);
+ GST_DEBUG_OBJECT (qtmux, "Pushing moov atoms");
+ gst_qt_mux_set_header_on_caps (qtmux, buf);
+ ret = gst_qt_mux_send_buffer (qtmux, buf, _offset, mind_fast);
+
+ return ret;
+
+serialize_error:
+ {
+ g_free (data);
+ return GST_FLOW_ERROR;
+ }
+}
+
+/* either calculates size of extra atoms or pushes them */
+static GstFlowReturn
+gst_qt_mux_send_extra_atoms (GstQTMux * qtmux, gboolean send, guint64 * offset,
+ gboolean mind_fast)
+{
+ GSList *walk;
+ guint64 loffset = 0, size = 0;
+ guint8 *data;
+ GstFlowReturn ret = GST_FLOW_OK;
+
+ for (walk = qtmux->extra_atoms; walk; walk = g_slist_next (walk)) {
+ AtomInfo *ainfo = (AtomInfo *) walk->data;
+
+ loffset = size = 0;
+ data = NULL;
+ if (!ainfo->copy_data_func (ainfo->atom,
+ send ? &data : NULL, &size, &loffset))
+ goto serialize_error;
+
+ if (send) {
+ GstBuffer *buf;
+
+ GST_DEBUG_OBJECT (qtmux,
+ "Pushing extra top-level atom %" GST_FOURCC_FORMAT,
+ GST_FOURCC_ARGS (ainfo->atom->type));
+ buf = _gst_buffer_new_take_data (data, loffset);
+ ret = gst_qt_mux_send_buffer (qtmux, buf, offset, FALSE);
+ if (ret != GST_FLOW_OK)
+ break;
+ } else {
+ if (offset)
+ *offset += loffset;
+ }
+ }
+
+ return ret;
+
+serialize_error:
+ {
+ g_free (data);
+ return GST_FLOW_ERROR;
+ }
+}
+
+static GstFlowReturn
+gst_qt_mux_start_file (GstQTMux * qtmux)
+{
+ GstFlowReturn ret = GST_FLOW_OK;
+ GstCaps *caps;
+
+ GST_DEBUG_OBJECT (qtmux, "starting file");
+
+ caps = gst_caps_copy (gst_pad_get_pad_template_caps (qtmux->srcpad));
+ /* qtmux has structure with and without variant, remove all but the first */
+ while (gst_caps_get_size (caps) > 1)
+ gst_caps_remove_structure (caps, 1);
+ gst_pad_set_caps (qtmux->srcpad, caps);
+ gst_caps_unref (caps);
+
+ /* 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));
+
+ /* initialize our moov recovery file */
+ GST_OBJECT_LOCK (qtmux);
+ if (qtmux->moov_recov_file_path) {
+ GST_DEBUG_OBJECT (qtmux, "Openning moov recovery file: %s",
+ qtmux->moov_recov_file_path);
+ qtmux->moov_recov_file = g_fopen (qtmux->moov_recov_file_path, "wb+");
+ if (qtmux->moov_recov_file == NULL) {
+ GST_WARNING_OBJECT (qtmux, "Failed to open moov recovery file in %s",
+ qtmux->moov_recov_file_path);
+ } else {
+ GSList *walk;
+ gboolean fail = FALSE;
+ AtomFTYP *ftyp = NULL;
+ GstBuffer *prefix = NULL;
+
+ gst_qt_mux_prepare_ftyp (qtmux, &ftyp, &prefix);
+
+ if (!atoms_recov_write_headers (qtmux->moov_recov_file, ftyp, prefix,
+ qtmux->moov, qtmux->timescale,
+ g_slist_length (qtmux->sinkpads))) {
+ GST_WARNING_OBJECT (qtmux, "Failed to write moov recovery file "
+ "headers");
+ fail = TRUE;
+ }
+
+ atom_ftyp_free (ftyp);
+ if (prefix)
+ gst_buffer_unref (prefix);
+
+ for (walk = qtmux->sinkpads; walk && !fail; walk = g_slist_next (walk)) {
+ GstCollectData *cdata = (GstCollectData *) walk->data;
+ GstQTPad *qpad = (GstQTPad *) cdata;
+ /* write info for each stream */
+ fail = atoms_recov_write_trak_info (qtmux->moov_recov_file, qpad->trak);
+ if (fail) {
+ GST_WARNING_OBJECT (qtmux, "Failed to write trak info to recovery "
+ "file");
+ }
+ }
+ if (fail) {
+ /* cleanup */
+ fclose (qtmux->moov_recov_file);
+ qtmux->moov_recov_file = NULL;
+ GST_WARNING_OBJECT (qtmux, "An error was detected while writing to "
+ "recover file, moov recovery won't work");
+ }
+ }
+ }
+ GST_OBJECT_UNLOCK (qtmux);
+
+ /*
+ * 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;
+ }
+
+ /* well, it's moov pos if fragmented ... */
+ qtmux->mdat_pos = qtmux->header_size;
+
+ if (qtmux->fragment_duration) {
+ GST_DEBUG_OBJECT (qtmux, "fragment duration %d ms, writing headers",
+ qtmux->fragment_duration);
+ /* also used as snapshot marker to indicate fragmented file */
+ qtmux->fragment_sequence = 1;
+ /* prepare moov and/or tags */
+ gst_qt_mux_configure_moov (qtmux, NULL);
+ gst_qt_mux_setup_metadata (qtmux);
+ ret = gst_qt_mux_send_moov (qtmux, &qtmux->header_size, FALSE);
+ if (ret != GST_FLOW_OK)
+ return ret;
+ /* extra atoms */
+ ret =
+ gst_qt_mux_send_extra_atoms (qtmux, TRUE, &qtmux->header_size, FALSE);
+ if (ret != GST_FLOW_OK)
+ return ret;
+ /* prepare index */
+ if (!qtmux->streamable)
+ qtmux->mfra = atom_mfra_new (qtmux->context);
+ } else {
+ /* extended to ensure some spare space */
+ 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;
+ guint64 offset = 0, size = 0;
+ GSList *walk;
+ gboolean large_file;
+ guint32 timescale;
+ GstClockTime first_ts = GST_CLOCK_TIME_NONE;
+
+ 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));
+
+ if (!GST_CLOCK_TIME_IS_VALID (qtpad->first_ts)) {
+ GST_DEBUG_OBJECT (qtmux, "Pad %s has no buffers",
+ GST_PAD_NAME (qtpad->collect.pad));
+ continue;
+ }
+
+ /* determine max stream duration */
+ if (!GST_CLOCK_TIME_IS_VALID (first_ts) ||
+ (GST_CLOCK_TIME_IS_VALID (qtpad->first_ts) &&
+ qtpad->last_dts > first_ts)) {
+ first_ts = qtpad->last_dts;
+ }
+ }
+
+ if (qtmux->fragment_sequence) {
+ GstEvent *event;
+
+ if (qtmux->mfra) {
+ guint8 *data = NULL;
+ GstBuffer *buf;
+
+ size = offset = 0;
+ GST_DEBUG_OBJECT (qtmux, "adding mfra");
+ if (!atom_mfra_copy_data (qtmux->mfra, &data, &size, &offset))
+ goto serialize_error;
+ buf = _gst_buffer_new_take_data (data, offset);
+ ret = gst_qt_mux_send_buffer (qtmux, buf, NULL, FALSE);
+ if (ret != GST_FLOW_OK)
+ return ret;
+ } else {
+ /* must have been streamable; no need to write duration */
+ GST_DEBUG_OBJECT (qtmux, "streamable file; nothing to stop");
+ return GST_FLOW_OK;
+ }
+
+
+ timescale = qtmux->timescale;
+ /* only mvex duration is updated,
+ * mvhd should be consistent with empty moov
+ * (but TODO maybe some clients do not handle that well ?) */
+ qtmux->moov->mvex.mehd.fragment_duration =
+ gst_util_uint64_scale (first_ts, timescale, GST_SECOND);
+ GST_DEBUG_OBJECT (qtmux, "rewriting moov with mvex duration %"
+ GST_TIME_FORMAT, GST_TIME_ARGS (first_ts));
+ /* seek and rewrite the header */
+ event = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_BYTES,
+ qtmux->mdat_pos, GST_CLOCK_TIME_NONE, 0);
+ gst_pad_push_event (qtmux->srcpad, event);
+ /* no need to seek back */
+ return gst_qt_mux_send_moov (qtmux, NULL, FALSE);
+ }
+
+ gst_qt_mux_configure_moov (qtmux, &timescale);
+
+ /* check for late streams */
+ first_ts = GST_CLOCK_TIME_NONE;
+ for (walk = qtmux->collect->data; walk; walk = g_slist_next (walk)) {
+ GstCollectData *cdata = (GstCollectData *) walk->data;
+ GstQTPad *qtpad = (GstQTPad *) cdata;
+
+ if (!GST_CLOCK_TIME_IS_VALID (first_ts) ||
+ (GST_CLOCK_TIME_IS_VALID (qtpad->first_ts) &&
+ qtpad->first_ts < first_ts)) {
+ first_ts = qtpad->first_ts;
+ }
+ }
+ GST_DEBUG_OBJECT (qtmux, "Media first ts selected: %" GST_TIME_FORMAT,
+ GST_TIME_ARGS (first_ts));
+ /* add EDTSs for late streams */
+ for (walk = qtmux->collect->data; walk; walk = g_slist_next (walk)) {
+ GstCollectData *cdata = (GstCollectData *) walk->data;
+ GstQTPad *qtpad = (GstQTPad *) cdata;
+ guint32 lateness;
+ guint32 duration;
+
+ if (GST_CLOCK_TIME_IS_VALID (qtpad->first_ts) &&
+ qtpad->first_ts > first_ts + MAX_TOLERATED_LATENESS) {
+ GST_DEBUG_OBJECT (qtmux, "Pad %s is a late stream by %" GST_TIME_FORMAT,
+ GST_PAD_NAME (qtpad->collect.pad),
+ GST_TIME_ARGS (qtpad->first_ts - first_ts));
+ lateness = gst_util_uint64_scale_round (qtpad->first_ts - first_ts,
+ timescale, GST_SECOND);
+ duration = qtpad->trak->tkhd.duration;
+ atom_trak_add_elst_entry (qtpad->trak, lateness, (guint32) - 1,
+ (guint32) (1 * 65536.0));
+ atom_trak_add_elst_entry (qtpad->trak, duration, 0,
+ (guint32) (1 * 65536.0));
+
+ /* need to add the empty time to the trak duration */
+ qtpad->trak->tkhd.duration += lateness;
+ }
+ }
+
+ /* 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,
+ offset);
+ offset += qtmux->header_size + (large_file ? 16 : 8);
+
+ /* sum up with the extra atoms size */
+ ret = gst_qt_mux_send_extra_atoms (qtmux, FALSE, &offset, FALSE);
+ if (ret != GST_FLOW_OK)
+ return ret;
+ } else {
+ offset = qtmux->header_size;
+ }
+ atom_moov_chunks_add_offset (qtmux->moov, offset);
+
+ /* moov */
+ /* note: as of this point, we no longer care about tracking written data size,
+ * since there is no more use for it anyway */
+ ret = gst_qt_mux_send_moov (qtmux, NULL, FALSE);
+ if (ret != GST_FLOW_OK)
+ return ret;
+
+ /* extra atoms */
+ ret = gst_qt_mux_send_extra_atoms (qtmux, TRUE, NULL, FALSE);
+ if (ret != GST_FLOW_OK)
+ return ret;
+
+ /* if needed, send mdat atom and move buffered data into it */
+ if (qtmux->fast_start_file) {
+ /* mdat_size = accumulated (buffered data) */
+ 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 {
+ /* mdat needs update iff not using faststart */
+ GST_DEBUG_OBJECT (qtmux, "updating mdat 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 no longer write anything anyway */
+ }
+
+ return ret;
+
+ /* ERRORS */
+serialize_error:
+ {
+ 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;
+ }
+}
+
+static GstFlowReturn
+gst_qt_mux_pad_fragment_add_buffer (GstQTMux * qtmux, GstQTPad * pad,
+ GstBuffer * buf, gboolean force, guint32 nsamples, gint64 dts,
+ guint32 delta, guint32 size, gboolean sync, gint64 pts_offset)
+{
+ GstFlowReturn ret = GST_FLOW_OK;
+
+ /* setup if needed */
+ if (G_UNLIKELY (!pad->traf || force))
+ goto init;
+
+flush:
+ /* flush pad fragment if threshold reached,
+ * or at new keyframe if we should be minding those in the first place */
+ if (G_UNLIKELY (force || (sync && pad->sync) ||
+ pad->fragment_duration < (gint64) delta)) {
+ AtomMOOF *moof;
+ guint64 size = 0, offset = 0;
+ guint8 *data = NULL;
+ GstBuffer *buffer;
+ guint i, total_size;
+
+ /* now we know where moof ends up, update offset in tfra */
+ if (pad->tfra)
+ atom_tfra_update_offset (pad->tfra, qtmux->header_size);
+
+ moof = atom_moof_new (qtmux->context, qtmux->fragment_sequence);
+ /* takes ownership */
+ atom_moof_add_traf (moof, pad->traf);
+ pad->traf = NULL;
+ atom_moof_copy_data (moof, &data, &size, &offset);
+ buffer = _gst_buffer_new_take_data (data, offset);
+ GST_LOG_OBJECT (qtmux, "writing moof size %d", GST_BUFFER_SIZE (buffer));
+ ret = gst_qt_mux_send_buffer (qtmux, buffer, &qtmux->header_size, FALSE);
+
+ /* and actual data */
+ total_size = 0;
+ for (i = 0; i < atom_array_get_len (&pad->fragment_buffers); i++) {
+ total_size +=
+ GST_BUFFER_SIZE (atom_array_index (&pad->fragment_buffers, i));
+ }
+
+ GST_LOG_OBJECT (qtmux, "writing %d buffers, total_size %d",
+ atom_array_get_len (&pad->fragment_buffers), total_size);
+ if (ret == GST_FLOW_OK)
+ ret = gst_qt_mux_send_mdat_header (qtmux, &qtmux->header_size, total_size,
+ FALSE);
+ for (i = 0; i < atom_array_get_len (&pad->fragment_buffers); i++) {
+ if (G_LIKELY (ret == GST_FLOW_OK))
+ ret = gst_qt_mux_send_buffer (qtmux,
+ atom_array_index (&pad->fragment_buffers, i), &qtmux->header_size,
+ FALSE);
+ else
+ gst_buffer_unref (atom_array_index (&pad->fragment_buffers, i));
+ }
+
+ atom_array_clear (&pad->fragment_buffers);
+ atom_moof_free (moof);
+ qtmux->fragment_sequence++;
+ force = FALSE;
+ }
+
+init:
+ if (G_UNLIKELY (!pad->traf)) {
+ GST_LOG_OBJECT (qtmux, "setting up new fragment");
+ pad->traf = atom_traf_new (qtmux->context, atom_trak_get_id (pad->trak));
+ atom_array_init (&pad->fragment_buffers, 512);
+ pad->fragment_duration = gst_util_uint64_scale (qtmux->fragment_duration,
+ atom_trak_get_timescale (pad->trak), 1000);
+
+ if (G_UNLIKELY (qtmux->mfra && !pad->tfra)) {
+ pad->tfra = atom_tfra_new (qtmux->context, atom_trak_get_id (pad->trak));
+ atom_mfra_add_tfra (qtmux->mfra, pad->tfra);
+ }
+ }
+
+ /* add buffer and metadata */
+ atom_traf_add_samples (pad->traf, delta, size, sync, pts_offset,
+ pad->sync && sync);
+ atom_array_append (&pad->fragment_buffers, buf, 256);
+ pad->fragment_duration -= delta;
+
+ if (pad->tfra) {
+ guint32 sn = atom_traf_get_sample_num (pad->traf);
+
+ if ((sync && pad->sync) || (sn == 1 && !pad->sync))
+ atom_tfra_add_entry (pad->tfra, dts, sn);
+ }
+
+ if (G_UNLIKELY (force))
+ goto flush;
+
+ return ret;
+}
+
+/* sigh, tiny list helpers to re-order stuff */
+static void
+gst_qt_mux_push_ts (GstQTMux * qtmux, GstQTPad * pad, GstClockTime ts)
+{
+ gint i;
+
+ for (i = 0; (i < QTMUX_NO_OF_TS) && (i < pad->ts_n_entries); i++) {
+ if (ts > pad->ts_entries[i])
+ break;
+ }
+ memmove (&pad->ts_entries[i + 1], &pad->ts_entries[i],
+ sizeof (GstClockTime) * (pad->ts_n_entries - i));
+ pad->ts_entries[i] = ts;
+ pad->ts_n_entries++;
+}
+
+/* takes ownership of @buf */
+static GstBuffer *
+gst_qt_mux_get_asc_buffer_ts (GstQTMux * qtmux, GstQTPad * pad, GstBuffer * buf)
+{
+ const gint wrap = G_N_ELEMENTS (pad->buf_entries);
+ GstClockTime ts;
+
+ /* store buffer and ts, latter ordered */
+ if (buf) {
+ pad->buf_entries[pad->buf_tail++] = buf;
+ pad->buf_tail %= wrap;
+ gst_qt_mux_push_ts (qtmux, pad, GST_BUFFER_TIMESTAMP (buf));
+ }
+
+ if (pad->ts_n_entries && (!buf || pad->ts_n_entries >= QTMUX_NO_OF_TS)) {
+ ts = pad->ts_entries[--pad->ts_n_entries];
+ buf = pad->buf_entries[pad->buf_head];
+ pad->buf_entries[pad->buf_head++] = NULL;
+ pad->buf_head %= wrap;
+ buf = gst_buffer_make_metadata_writable (buf);
+ /* track original ts (= pts ?) for later */
+ GST_BUFFER_OFFSET_END (buf) = GST_BUFFER_TIMESTAMP (buf);
+ GST_BUFFER_TIMESTAMP (buf) = ts;
+ GST_DEBUG_OBJECT (qtmux, "next buffer uses reordered ts %" GST_TIME_FORMAT,
+ GST_TIME_ARGS (ts));
+ } else {
+ buf = NULL;
+ }
+
+ return buf;
+}
+
+/*
+ * 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 chunk_offset;
+ gint64 last_dts, scaled_duration;
+ gint64 pts_offset = 0;
+ gboolean sync = FALSE, do_pts = FALSE;
+ gboolean drain = (buf == NULL);
+ GstFlowReturn ret = GST_FLOW_OK;
+
+ if (!pad->fourcc)
+ goto not_negotiated;
+
+ /* if this pad has a prepare function, call it */
+ if (pad->prepare_buf_func != NULL) {
+ buf = pad->prepare_buf_func (pad, buf, qtmux);
+ }
+
+again:
+ last_buf = pad->last_buf;
+ if (G_UNLIKELY (qtmux->dts_method == DTS_METHOD_REORDER)) {
+ buf = gst_qt_mux_get_asc_buffer_ts (qtmux, pad, buf);
+ if (!buf && !last_buf) {
+ GST_DEBUG_OBJECT (qtmux, "no reordered buffer");
+ return GST_FLOW_OK;
+ }
+ }
+
+ 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;
+ goto exit;
+ } else
+ gst_buffer_ref (last_buf);
+
+ /* nasty heuristic mess to guestimate dealing with DTS/PTS,
+ * while also trying to stay close to input ts to preserve sync,
+ * so in DTS_METHOD_DD:
+ * - prefer using input ts where possible
+ * - if those detected out-of-order (*), mark as out-of-order
+ * - if in out-of-order, then
+ * - if duration available, use that as delta
+ * Also mind to preserve sync between streams, and adding
+ * durations might drift, so try to resync when we expect
+ * input ts == (sum of durations), which is at some keyframe input frame.
+ * - if no duration available, we are actually in serious trouble and need
+ * to hack around that, so we fail.
+ * To remedy failure, alternatively, in DTS_METHOD_REORDER:
+ * - collect some buffers and re-order timestamp,
+ * then process the oldest buffer with smallest timestamps.
+ * This should typically compensate for some codec's handywork with ts.
+ * ... but in case this makes ts end up where not expected, in DTS_METHOD_ASC:
+ * - keep each ts with its buffer and still keep a list of most recent X ts,
+ * use the (ascending) minimum of those as DTS (and the difference as ts delta),
+ * and use this DTS as a basis to obtain a (positive) CTS offset.
+ * This should yield exact PTS == buffer ts, but it seems not all players
+ * out there are aware of ctts pts ...
+ *
+ * 0.11 Phew, can we (pretty) please please sort out DTS/PTS on buffers ...
+ */
+ if (G_LIKELY (buf) && !pad->is_out_of_order) {
+ if (G_LIKELY (GST_BUFFER_TIMESTAMP_IS_VALID (last_buf) &&
+ GST_BUFFER_TIMESTAMP_IS_VALID (buf))) {
+ if ((GST_BUFFER_TIMESTAMP (buf) < GST_BUFFER_TIMESTAMP (last_buf))) {
+ GST_DEBUG_OBJECT (qtmux, "detected out-of-order input");
+ pad->is_out_of_order = TRUE;
+ }
+ } else {
+ /* this is pretty bad */
+ GST_WARNING_OBJECT (qtmux, "missing input timestamp");
+ /* fall back to durations */
+ pad->is_out_of_order = TRUE;
+ }
+ }
+
+ /* would have to be some unusual input, but not impossible */
+ if (G_UNLIKELY (qtmux->dts_method == DTS_METHOD_REORDER &&
+ pad->is_out_of_order)) {
+ goto no_order;
+ }
+
+ /* fall back to duration if last buffer or
+ * out-of-order (determined previously), otherwise use input ts */
+ if (buf == NULL ||
+ (pad->is_out_of_order && qtmux->dts_method == DTS_METHOD_DD)) {
+ 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);
+ /* avoid drift in sum timestamps,
+ * so use input timestamp for suitable keyframe */
+ if (buf && !GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT) &&
+ GST_BUFFER_TIMESTAMP (buf) >= pad->last_dts) {
+ GST_DEBUG_OBJECT (qtmux, "resyncing out-of-order input to ts; "
+ "replacing %" GST_TIME_FORMAT " by %" GST_TIME_FORMAT,
+ GST_TIME_ARGS (pad->last_dts + duration),
+ GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)));
+ duration = GST_BUFFER_TIMESTAMP (buf) - pad->last_dts;
+ }
+ }
+ } else if (qtmux->dts_method != DTS_METHOD_ASC) {
+ duration = GST_BUFFER_TIMESTAMP (buf) - GST_BUFFER_TIMESTAMP (last_buf);
+ } else {
+ GstClockTime ts;
+
+ g_assert (qtmux->dts_method == DTS_METHOD_ASC);
+ if (!qtmux->guess_pts)
+ goto need_pts;
+
+ /* add timestamp to queue; keeps in descending order */
+ gst_qt_mux_push_ts (qtmux, pad, GST_BUFFER_TIMESTAMP (last_buf));
+ /* chuck out smallest/last one if we have enough */
+ if (G_LIKELY (pad->ts_n_entries > QTMUX_NO_OF_TS))
+ pad->ts_n_entries--;
+ /* peek the now smallest timestamp */
+ ts = pad->ts_entries[pad->ts_n_entries - 1];
+ /* these tails are expected to be (strictly) ascending with
+ * large enough history */
+ GST_DEBUG_OBJECT (qtmux, "ASC method; base timestamp %" GST_TIME_FORMAT,
+ GST_TIME_ARGS (ts));
+ if (ts >= pad->last_dts) {
+ duration = ts - pad->last_dts;
+ } else {
+ /* fallback to previous value, negative ct offset might handle */
+ GST_WARNING_OBJECT (qtmux, "unexpected decrease in timestamp");
+ duration = 0;
+ }
+ /* arrange for small non-zero duration/delta << expected frame time */
+ ts = gst_util_uint64_scale (10, GST_SECOND,
+ atom_trak_get_timescale (pad->trak));
+ duration = MAX (duration, ts);
+ }
+
+ gst_buffer_replace (&pad->last_buf, buf);
+
+ last_dts = gst_util_uint64_scale_round (pad->last_dts,
+ atom_trak_get_timescale (pad->trak), GST_SECOND);
+
+ /* fragments only deal with 1 buffer == 1 chunk (== 1 sample) */
+ if (pad->sample_size && !qtmux->fragment_sequence) {
+ /* Constant size packets: usually raw audio (with many samples per
+ buffer (= chunk)), but can also be fixed-packet-size codecs like ADPCM
+ */
+ 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 */
+ if (GST_BUFFER_DURATION (last_buf) != GST_CLOCK_TIME_NONE) {
+ nsamples = gst_util_uint64_scale_round (GST_BUFFER_DURATION (last_buf),
+ atom_trak_get_timescale (pad->trak), GST_SECOND);
+ } else {
+ 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_round (-pad->last_dts,
+ atom_trak_get_timescale (pad->trak), GST_SECOND);
+ } else {
+ scaled_dts = gst_util_uint64_scale_round (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_round (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)) {
+ guint64 pts;
+
+ pts = qtmux->dts_method == DTS_METHOD_REORDER ?
+ GST_BUFFER_OFFSET_END (last_buf) : GST_BUFFER_TIMESTAMP (last_buf);
+ pts = gst_util_uint64_scale_round (pts,
+ 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;
+ }
+
+ /* if this is the first buffer, store the timestamp */
+ if (G_UNLIKELY (pad->first_ts == GST_CLOCK_TIME_NONE) && last_buf) {
+ if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_TIMESTAMP (last_buf))) {
+ pad->first_ts = GST_BUFFER_TIMESTAMP (last_buf);
+ } else {
+ GST_DEBUG_OBJECT (qtmux, "First buffer for pad %s has no timestamp, "
+ "using 0 as first timestamp", GST_PAD_NAME (pad->collect.pad));
+ pad->first_ts = 0;
+ }
+ GST_DEBUG_OBJECT (qtmux, "Stored first timestamp for pad %s %"
+ GST_TIME_FORMAT, GST_PAD_NAME (pad->collect.pad),
+ GST_TIME_ARGS (pad->first_ts));
+ }
+
+ /* now we go and register this buffer/sample all over */
+ /* note that a new chunk is started each time (not fancy but works) */
+ if (qtmux->moov_recov_file) {
+ if (!atoms_recov_write_trak_samples (qtmux->moov_recov_file, pad->trak,
+ nsamples, (gint32) scaled_duration, sample_size, chunk_offset, sync,
+ do_pts, pts_offset)) {
+ GST_WARNING_OBJECT (qtmux, "Failed to write sample information to "
+ "recovery file, disabling recovery");
+ fclose (qtmux->moov_recov_file);
+ qtmux->moov_recov_file = NULL;
+ }
+ }
+
+ if (buf)
+ gst_buffer_unref (buf);
+
+ if (qtmux->fragment_sequence) {
+ /* ensure that always sync samples are marked as such */
+ ret = gst_qt_mux_pad_fragment_add_buffer (qtmux, pad, last_buf,
+ buf == NULL, nsamples, last_dts, (gint32) scaled_duration, sample_size,
+ !pad->sync || sync, pts_offset);
+ } else {
+ atom_trak_add_samples (pad->trak, nsamples, (gint32) scaled_duration,
+ sample_size, chunk_offset, sync, pts_offset);
+ ret = gst_qt_mux_send_buffer (qtmux, last_buf, &qtmux->mdat_size, TRUE);
+ }
+
+exit:
+ if (G_UNLIKELY (drain && qtmux->dts_method == DTS_METHOD_REORDER &&
+ ret == GST_FLOW_OK)) {
+ buf = NULL;
+ goto again;
+ }
+
+ return ret;
+
+ /* 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. "
+ "Using e.g. dts-method=reorder might help."));
+ goto bail;
+ }
+no_order:
+ {
+ GST_ELEMENT_ERROR (qtmux, STREAM, MUX, (NULL),
+ ("DTS method failed to re-order timestamps."));
+ goto bail;
+ }
+need_pts:
+ {
+ GST_ELEMENT_ERROR (qtmux, STREAM, MUX, (NULL),
+ ("Selected DTS method also needs PTS enabled."));
+ 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);
+
+ /* invalid should pass */
+ if (G_LIKELY (GST_CLOCK_TIME_IS_VALID (time))) {
+ time =
+ gst_segment_to_running_time (&data->segment, GST_FORMAT_TIME, time);
+ if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (time))) {
+ GST_DEBUG_OBJECT (qtmux, "clipping buffer on pad %s outside segment",
+ GST_PAD_NAME (data->pad));
+ buf = gst_collect_pads_pop (pads, data);
+ gst_buffer_unref (buf);
+ return GST_FLOW_OK;
+ }
+ }
+
+ 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);
+ buf = gst_buffer_make_metadata_writable (buf);
+ GST_BUFFER_TIMESTAMP (buf) = best_time;
+ ret = gst_qt_mux_add_buffer (qtmux, best_pad, buf);
+ } else {
+ ret = gst_qt_mux_stop_file (qtmux);
+ if (ret == GST_FLOW_OK) {
+ GST_DEBUG_OBJECT (qtmux, "Pushing eos");
+ gst_pad_push_event (qtmux->srcpad, gst_event_new_eos ());
+ ret = GST_FLOW_UNEXPECTED;
+ } else {
+ GST_WARNING_OBJECT (qtmux, "Failed to stop file: %s",
+ gst_flow_get_name (ret));
+ }
+ qtmux->state = GST_QT_MUX_STATE_EOS;
+ }
+
+ return ret;
+}
+
+static gboolean
+check_field (GQuark field_id, const GValue * value, gpointer user_data)
+{
+ GstStructure *structure = (GstStructure *) user_data;
+ const GValue *other = gst_structure_id_get_value (structure, field_id);
+ if (other == NULL)
+ return FALSE;
+ return gst_value_compare (value, other) == GST_VALUE_EQUAL;
+}
+
+static gboolean
+gst_qtmux_caps_is_subset_full (GstQTMux * qtmux, GstCaps * subset,
+ GstCaps * superset)
+{
+ GstStructure *sub_s = gst_caps_get_structure (subset, 0);
+ GstStructure *sup_s = gst_caps_get_structure (superset, 0);
+
+ return gst_structure_foreach (sub_s, check_field, sup_s);
+}
+
+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;
+ const gchar *stream_format;
+ GstCaps *current_caps = NULL;
+
+ /* find stream data */
+ qtpad = (GstQTPad *) gst_pad_get_element_private (pad);
+ g_assert (qtpad);
+
+ qtpad->prepare_buf_func = NULL;
+
+ /* does not go well to renegotiate stream mid-way, unless
+ * the old caps are a subset of the new one (this means upstream
+ * added more info to the caps, as both should be 'fixed' caps) */
+ if (qtpad->fourcc) {
+ g_object_get (pad, "caps", &current_caps, NULL);
+ g_assert (caps != NULL);
+
+ if (!gst_qtmux_caps_is_subset_full (qtmux, current_caps, caps)) {
+ goto refuse_renegotiation;
+ }
+ GST_DEBUG_OBJECT (qtmux,
+ "pad %s accepted renegotiation to %" GST_PTR_FORMAT " from %"
+ GST_PTR_FORMAT, GST_PAD_NAME (pad), caps, GST_PAD_CAPS (pad));
+ }
+
+ 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, qtpad->avg_bitrate,
+ qtpad->max_bitrate);
+ }
+ entry.samples_per_packet = 1152;
+ entry.bytes_per_sample = 2;
+ break;
+ }
+ break;
+ case 4:
+
+ /* check stream-format */
+ stream_format = gst_structure_get_string (structure, "stream-format");
+ if (stream_format) {
+ if (strcmp (stream_format, "raw") != 0) {
+ GST_WARNING_OBJECT (qtmux, "Unsupported AAC stream-format %s, "
+ "please use 'raw'", stream_format);
+ goto refuse_caps;
+ }
+ } else {
+ GST_WARNING_OBJECT (qtmux, "No stream-format present in caps, "
+ "assuming 'raw'");
+ }
+
+ 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");
+ }
+
+ /* AAC */
+ entry.fourcc = FOURCC_mp4a;
+
+ if (format == GST_QT_MUX_FORMAT_QT)
+ ext_atom = build_mov_aac_extension (qtpad->trak, codec_data,
+ qtpad->avg_bitrate, qtpad->max_bitrate);
+ else
+ ext_atom =
+ build_esds_extension (qtpad->trak, ESDS_OBJECT_TYPE_MPEG4_P3,
+ ESDS_STREAM_TYPE_AUDIO, codec_data, qtpad->avg_bitrate,
+ qtpad->max_bitrate);
+ 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_int (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;
+ } else if (strcmp (mimetype, "audio/x-adpcm") == 0) {
+ gint blocksize;
+ if (!gst_structure_get_int (structure, "block_align", &blocksize)) {
+ GST_DEBUG_OBJECT (qtmux, "broken caps, block_align missing");
+ goto refuse_caps;
+ }
+ /* Currently only supports WAV-style IMA ADPCM, for which the codec id is
+ 0x11 */
+ entry.fourcc = MS_WAVE_FOURCC (0x11);
+ /* 4 byte header per channel (including one sample). 2 samples per byte
+ remaining. Simplifying gives the following (samples per block per
+ channel) */
+ entry.samples_per_packet = 2 * blocksize / channels - 7;
+ entry.bytes_per_sample = 2;
+
+ entry.bytes_per_frame = blocksize;
+ entry.bytes_per_packet = blocksize / channels;
+ /* ADPCM has constant size packets */
+ constant_size = 1;
+ /* TODO: I don't really understand why this helps, but it does! Constant
+ * size and compression_id of -2 seem to be incompatible, and other files
+ * in the wild use this too. */
+ entry.compression_id = -1;
+
+ ext_atom = build_ima_adpcm_extension (channels, rate, blocksize);
+ } else if (strcmp (mimetype, "audio/x-alac") == 0) {
+ GstBuffer *codec_config;
+ gint len;
+
+ entry.fourcc = FOURCC_alac;
+ /* let's check if codec data already comes with 'alac' atom prefix */
+ if (!codec_data || (len = GST_BUFFER_SIZE (codec_data)) < 28) {
+ GST_DEBUG_OBJECT (qtmux, "broken caps, codec data missing");
+ goto refuse_caps;
+ }
+ if (GST_READ_UINT32_LE (GST_BUFFER_DATA (codec_data) + 4) == FOURCC_alac) {
+ len -= 8;
+ codec_config = gst_buffer_create_sub ((GstBuffer *) codec_data, 8, len);
+ } else {
+ codec_config = gst_buffer_ref ((GstBuffer *) codec_data);
+ }
+ if (len != 28) {
+ /* does not look good, but perhaps some trailing unneeded stuff */
+ GST_WARNING_OBJECT (qtmux, "unexpected codec-data size, possibly broken");
+ }
+ if (format == GST_QT_MUX_FORMAT_QT)
+ ext_atom = build_mov_alac_extension (qtpad->trak, codec_config);
+ else
+ ext_atom = build_codec_data_extension (FOURCC_alac, codec_config);
+ /* set some more info */
+ entry.bytes_per_sample = 2;
+ entry.samples_per_packet =
+ GST_READ_UINT32_BE (GST_BUFFER_DATA (codec_config) + 4);
+ gst_buffer_unref (codec_config);
+ }
+
+ 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,
+ qtmux->trak_timescale ? qtmux->trak_timescale : 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)
+{
+ if (rate == 0)
+ return 10000;
+
+ 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;
+ GList *ext_atom_list = NULL;
+ gboolean sync = FALSE;
+ int par_num, par_den;
+ GstCaps *current_caps = NULL;
+
+ /* find stream data */
+ qtpad = (GstQTPad *) gst_pad_get_element_private (pad);
+ g_assert (qtpad);
+
+ qtpad->prepare_buf_func = NULL;
+
+ /* does not go well to renegotiate stream mid-way, unless
+ * the old caps are a subset of the new one (this means upstream
+ * added more info to the caps, as both should be 'fixed' caps) */
+ if (qtpad->fourcc) {
+ g_object_get (pad, "caps", &current_caps, NULL);
+ g_assert (caps != NULL);
+
+ if (!gst_qtmux_caps_is_subset_full (qtmux, current_caps, caps)) {
+ goto refuse_renegotiation;
+ }
+ GST_DEBUG_OBJECT (qtmux,
+ "pad %s accepted renegotiation to %" GST_PTR_FORMAT " from %"
+ GST_PTR_FORMAT, GST_PAD_NAME (pad), caps, GST_PAD_CAPS (pad));
+ }
+
+ 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 = qtmux->trak_timescale ?
+ qtmux->trak_timescale : 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) {
+ ext_atom = NULL;
+ if (format == GST_QT_MUX_FORMAT_QT)
+ entry.fourcc = FOURCC_h263;
+ else
+ entry.fourcc = FOURCC_s263;
+ ext_atom = build_h263_extension ();
+ if (ext_atom != NULL)
+ ext_atom_list = g_list_prepend (ext_atom_list, ext_atom);
+ } 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, qtpad->avg_bitrate,
+ qtpad->max_bitrate);
+ if (ext_atom != NULL)
+ ext_atom_list = g_list_prepend (ext_atom_list, ext_atom);
+ 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) {
+ /* check if we accept these caps */
+ if (gst_structure_has_field (structure, "stream-format")) {
+ const gchar *format;
+ const gchar *alignment;
+
+ format = gst_structure_get_string (structure, "stream-format");
+ alignment = gst_structure_get_string (structure, "alignment");
+
+ if (strcmp (format, "avc") != 0 || alignment == NULL ||
+ strcmp (alignment, "au") != 0) {
+ GST_WARNING_OBJECT (qtmux, "Rejecting h264 caps, qtmux only accepts "
+ "avc format with AU aligned samples");
+ goto refuse_caps;
+ }
+ } else {
+ GST_WARNING_OBJECT (qtmux, "no stream-format field in h264 caps");
+ goto refuse_caps;
+ }
+
+ if (!codec_data) {
+ GST_WARNING_OBJECT (qtmux, "no codec_data in h264 caps");
+ goto refuse_caps;
+ }
+
+ entry.fourcc = FOURCC_avc1;
+ if (qtpad->avg_bitrate == 0) {
+ gint avg_bitrate = 0;
+ gst_structure_get_int (structure, "bitrate", &avg_bitrate);
+ qtpad->avg_bitrate = avg_bitrate;
+ }
+ ext_atom = build_btrt_extension (0, qtpad->avg_bitrate, qtpad->max_bitrate);
+ if (ext_atom != NULL)
+ ext_atom_list = g_list_prepend (ext_atom_list, ext_atom);
+ ext_atom = build_codec_data_extension (FOURCC_avcC, codec_data);
+ if (ext_atom != NULL)
+ ext_atom_list = g_list_prepend (ext_atom_list, ext_atom);
+ } else if (strcmp (mimetype, "video/x-svq") == 0) {
+ gint version = 0;
+ const GstBuffer *seqh = NULL;
+ const GValue *seqh_value;
+ gdouble gamma = 0;
+
+ gst_structure_get_int (structure, "svqversion", &version);
+ if (version == 3) {
+ entry.fourcc = FOURCC_SVQ3;
+ entry.version = 3;
+ entry.depth = 32;
+
+ seqh_value = gst_structure_get_value (structure, "seqh");
+ if (seqh_value) {
+ seqh = gst_value_get_buffer (seqh_value);
+ ext_atom = build_SMI_atom (seqh);
+ if (ext_atom)
+ ext_atom_list = g_list_prepend (ext_atom_list, ext_atom);
+ }
+
+ /* we need to add the gamma anyway because quicktime might crash
+ * when it doesn't find it */
+ if (!gst_structure_get_double (structure, "applied-gamma", &gamma)) {
+ /* it seems that using 0 here makes it ignored */
+ gamma = 0.0;
+ }
+ ext_atom = build_gama_atom (gamma);
+ if (ext_atom)
+ ext_atom_list = g_list_prepend (ext_atom_list, ext_atom);
+ } else {
+ GST_WARNING_OBJECT (qtmux, "SVQ version %d not supported. Please file "
+ "a bug at http://bugzilla.gnome.org", version);
+ }
+ } 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 ||
+ strcmp (mimetype, "image/x-jpc") == 0) {
+ guint32 fourcc;
+ const GValue *cmap_array;
+ const GValue *cdef_array;
+ gint ncomp = 0;
+ gint fields = 1;
+
+ if (strcmp (mimetype, "image/x-jpc") == 0) {
+ qtpad->prepare_buf_func = gst_qt_mux_prepare_jpc_buffer;
+ }
+
+ gst_structure_get_int (structure, "num-components", &ncomp);
+ gst_structure_get_int (structure, "fields", &fields);
+ cmap_array = gst_structure_get_value (structure, "component-map");
+ cdef_array = gst_structure_get_value (structure, "channel-definitions");
+
+ ext_atom = NULL;
+ entry.fourcc = FOURCC_mjp2;
+ sync = FALSE;
+ if (gst_structure_get_fourcc (structure, "fourcc", &fourcc) &&
+ (ext_atom =
+ build_jp2h_extension (qtpad->trak, width, height, fourcc, ncomp,
+ cmap_array, cdef_array)) != NULL) {
+ ext_atom_list = g_list_append (ext_atom_list, ext_atom);
+
+ ext_atom = build_fiel_extension (fields);
+ if (ext_atom)
+ ext_atom_list = g_list_append (ext_atom_list, ext_atom);
+
+ ext_atom = build_jp2x_extension (codec_data);
+ if (ext_atom)
+ ext_atom_list = g_list_append (ext_atom_list, ext_atom);
+ } else {
+ GST_DEBUG_OBJECT (qtmux, "missing or invalid fourcc in jp2 caps");
+ goto refuse_caps;
+ }
+ } else if (strcmp (mimetype, "video/x-vp8") == 0) {
+ entry.fourcc = FOURCC_VP80;
+ sync = FALSE;
+ } else if (strcmp (mimetype, "video/x-qt-part") == 0) {
+ guint32 fourcc;
+
+ gst_structure_get_fourcc (structure, "format", &fourcc);
+ entry.fourcc = fourcc;
+ 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->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_list);
+
+ 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;
+ guint32 avg_bitrate = 0, max_bitrate = 0;
+
+ 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);
+ GstTagMergeMode mode;
+
+ GST_OBJECT_LOCK (qtmux);
+ 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);
+ GST_OBJECT_UNLOCK (qtmux);
+
+ if (gst_tag_list_get_uint (list, GST_TAG_BITRATE, &avg_bitrate) |
+ gst_tag_list_get_uint (list, GST_TAG_MAXIMUM_BITRATE, &max_bitrate)) {
+ GstQTPad *qtpad = gst_pad_get_element_private (pad);
+ g_assert (qtpad);
+
+ if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32)
+ qtpad->avg_bitrate = avg_bitrate;
+ if (max_bitrate > 0 && max_bitrate < G_MAXUINT32)
+ qtpad->max_bitrate = max_bitrate;
+ }
+
+ 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);
+ GSList *walk;
+
+ GST_DEBUG_OBJECT (element, "Releasing %s:%s", GST_DEBUG_PAD_NAME (pad));
+
+ for (walk = mux->sinkpads; walk; walk = g_slist_next (walk)) {
+ GstQTPad *qtpad = (GstQTPad *) walk->data;
+ GST_DEBUG ("Checking %s:%s", GST_DEBUG_PAD_NAME (qtpad->collect.pad));
+ if (qtpad->collect.pad == pad) {
+ /* this is it, remove */
+ mux->sinkpads = g_slist_delete_link (mux->sinkpads, walk);
+ gst_element_remove_pad (element, pad);
+ break;
+ }
+ }
+
+ gst_collect_pads_remove_pad (mux->collect, 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_STARTED)
+ 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);
+
+ qtmux->sinkpads = g_slist_append (qtmux->sinkpads, collect_pad);
+
+ /* 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_MOVIE_TIMESCALE:
+ g_value_set_uint (value, qtmux->timescale);
+ break;
+ case PROP_TRAK_TIMESCALE:
+ g_value_set_uint (value, qtmux->trak_timescale);
+ break;
+ case PROP_DO_CTTS:
+ g_value_set_boolean (value, qtmux->guess_pts);
+ break;
+ case PROP_DTS_METHOD:
+ g_value_set_enum (value, qtmux->dts_method);
+ 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;
+ case PROP_MOOV_RECOV_FILE:
+ g_value_set_string (value, qtmux->moov_recov_file_path);
+ break;
+ case PROP_FRAGMENT_DURATION:
+ g_value_set_uint (value, qtmux->fragment_duration);
+ break;
+ case PROP_STREAMABLE:
+ g_value_set_boolean (value, qtmux->streamable);
+ 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;
+
+ 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_MOVIE_TIMESCALE:
+ qtmux->timescale = g_value_get_uint (value);
+ break;
+ case PROP_TRAK_TIMESCALE:
+ qtmux->trak_timescale = g_value_get_uint (value);
+ break;
+ case PROP_DO_CTTS:
+ qtmux->guess_pts = g_value_get_boolean (value);
+ break;
+ case PROP_DTS_METHOD:
+ qtmux->dts_method = g_value_get_enum (value);
+ break;
+ case PROP_FAST_START:
+ qtmux->fast_start = g_value_get_boolean (value);
+ break;
+ case PROP_FAST_START_TEMP_FILE:
+ 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;
+ case PROP_MOOV_RECOV_FILE:
+ g_free (qtmux->moov_recov_file_path);
+ qtmux->moov_recov_file_path = g_value_dup_string (value);
+ break;
+ case PROP_FRAGMENT_DURATION:
+ qtmux->fragment_duration = g_value_get_uint (value);
+ break;
+ case PROP_STREAMABLE:
+ qtmux->streamable = g_value_get_boolean (value);
+ 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
+ };
+ static const GInterfaceInfo tag_xmp_writer_info = {
+ NULL, NULL, NULL
+ };
+ GType type;
+ GstQTMuxFormat format;
+ GstQTMuxClassParams *params;
+ guint i = 0;
+
+ GST_DEBUG_CATEGORY_INIT (gst_qt_mux_debug, "qtmux", 0, "QT Muxer");
+
+ 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);
+ g_type_add_interface_static (type, GST_TYPE_TAG_XMP_WRITER,
+ &tag_xmp_writer_info);
+
+ if (!gst_element_register (plugin, prop->name, GST_RANK_PRIMARY, type))
+ return FALSE;
+
+ i++;
+ }
+
+ GST_LOG ("Finished registering muxers");
+
+ /* FIXME: ideally classification tag should be added and
+ registered in gstreamer core gsttaglist
+ */
+
+ GST_LOG ("Registering tags");
+
+ gst_tag_register (GST_TAG_3GP_CLASSIFICATION, GST_TAG_FLAG_META,
+ G_TYPE_STRING, GST_TAG_3GP_CLASSIFICATION, "content classification",
+ gst_tag_merge_use_first);
+
+ GST_LOG ("Finished registering tags");
+
+ return TRUE;
+}
diff --git a/gst/quicktime/gstqtmux.h b/gst/quicktime/gstqtmux.h
new file mode 100644
index 000000000..3a2cb492f
--- /dev/null
+++ b/gst/quicktime/gstqtmux.h
@@ -0,0 +1,228 @@
+/* Quicktime muxer plugin for GStreamer
+ * Copyright (C) 2008-2010 Thiago 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 "atomsrecovery.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 GstQTPad;
+
+/*
+ * GstQTPadPrepareBufferFunc
+ *
+ * Receives a buffer (takes ref) and returns a new buffer that should
+ * replace the passed one.
+ *
+ * Useful for when the pad/datatype needs some manipulation before
+ * being muxed. (Originally added for image/x-jpc support, for which buffers
+ * need to be wrapped into a isom box)
+ */
+typedef GstBuffer * (*GstQTPadPrepareBufferFunc) (GstQTPad * pad,
+ GstBuffer * buf, GstQTMux * qtmux);
+
+#define QTMUX_NO_OF_TS 10
+
+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;
+ /* bitrates */
+ guint32 avg_bitrate, max_bitrate;
+
+ GstBuffer *last_buf;
+ /* dts of last_buf */
+ GstClockTime last_dts;
+
+ /* store the first timestamp for comparing with other streams and
+ * know if there are late streams */
+ GstClockTime first_ts;
+ GstClockTime ts_entries[QTMUX_NO_OF_TS + 2];
+ guint ts_n_entries;
+ GstBuffer *buf_entries[QTMUX_NO_OF_TS + 2];
+ guint buf_head;
+ guint buf_tail;
+
+ /* all the atom and chunk book-keeping is delegated here
+ * unowned/uncounted reference, parent MOOV owns */
+ AtomTRAK *trak;
+ /* fragmented support */
+ /* meta data book-keeping delegated here */
+ AtomTRAF *traf;
+ /* fragment buffers */
+ ATOM_ARRAY (GstBuffer *) fragment_buffers;
+ /* running fragment duration */
+ gint64 fragment_duration;
+ /* optional fragment index book-keeping */
+ AtomTFRA *tfra;
+
+ /* if nothing is set, it won't be called */
+ GstQTPadPrepareBufferFunc prepare_buf_func;
+};
+
+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;
+ GSList *sinkpads;
+
+ /* 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;
+ GSList *extra_atoms; /* list of extra top-level atoms (e.g. UUID for xmp)
+ * Stored as AtomInfo structs */
+
+ /* fragmented file index */
+ AtomMFRA *mfra;
+
+ /* fast start */
+ FILE *fast_start_file;
+
+ /* moov recovery */
+ FILE *moov_recov_file;
+
+ /* fragment sequence */
+ guint32 fragment_sequence;
+
+ /* properties */
+ guint32 timescale;
+ guint32 trak_timescale;
+ AtomsTreeFlavor flavor;
+ gboolean fast_start;
+ gboolean guess_pts;
+ gint dts_method;
+ gchar *fast_start_file_path;
+ gchar *moov_recov_file_path;
+ guint32 fragment_duration;
+ gboolean streamable;
+
+ /* 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);
+gboolean gst_qt_mux_register (GstPlugin * plugin);
+
+/* FIXME: ideally classification tag should be added and
+ * registered in gstreamer core gsttaglist
+ *
+ * this tag is a string in the format: entityfourcc://table_num/content
+ * FIXME Shouldn't we add a field for 'language'?
+ */
+#define GST_TAG_3GP_CLASSIFICATION "classification"
+
+G_END_DECLS
+
+#endif /* __GST_QT_MUX_H__ */
diff --git a/gst/quicktime/gstqtmuxmap.c b/gst/quicktime/gstqtmuxmap.c
new file mode 100644
index 000000000..a14367ea7
--- /dev/null
+++ b/gst/quicktime/gstqtmuxmap.c
@@ -0,0 +1,370 @@
+/* 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, " \
+ "stream-format = (string) avc, " \
+ "alignment = (string) au, " \
+ 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 SVQ_CAPS \
+ "video/x-svq, " \
+ "svqversion = (int) 3, " \
+ 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, " \
+ "stream-format = (string) raw, " \
+ 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 ] "
+
+#define ADPCM_CAPS \
+ "audio/x-adpcm, " \
+ "layout = (string)dvi, " \
+ "block_align = (int)[64, 8096], " \
+ COMMON_AUDIO_CAPS(2, MAX)
+
+#define ALAC_CAPS \
+ "audio/x-alac, " \
+ COMMON_AUDIO_CAPS(2, MAX)
+
+/* 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; "
+ "video/quicktime"),
+ 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 "; "
+ SVQ_CAPS "; "
+ "video/x-dv, "
+ "systemstream = (boolean) false, "
+ COMMON_VIDEO_CAPS "; "
+ "image/jpeg, "
+ COMMON_VIDEO_CAPS_NO_FRAMERATE "; "
+ "video/x-vp8, "
+ COMMON_VIDEO_CAPS "; " "video/x-qt-part, " COMMON_VIDEO_CAPS),
+ GST_STATIC_CAPS (PCM_CAPS_FULL "; "
+ MP3_CAPS " ; "
+ AAC_CAPS " ; "
+ ADPCM_CAPS " ; "
+ "audio/x-alaw, " COMMON_AUDIO_CAPS (2, MAX) "; "
+ AMR_CAPS " ; " ALAC_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 " ; " ALAC_CAPS)
+ }
+ ,
+ /* Microsoft Smooth Streaming fmp4/isml */
+ /* TODO add WMV/WMA support */
+ {
+ GST_QT_MUX_FORMAT_ISML,
+ "ismlmux",
+ "ISML",
+ "GstISMLMux",
+ GST_STATIC_CAPS ("video/quicktime, variant = (string) iso"),
+ GST_STATIC_CAPS (MPEG4V_CAPS "; " H264_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 "; "
+ "image/x-jpc, " 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 if (format == GST_QT_MUX_FORMAT_ISML)
+ return ATOMS_TREE_FLAVOR_ISML;
+ 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 isml_brands[] = { 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_ISML:
+ major = FOURCC_isml;
+ comp = isml_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 */
+}
diff --git a/gst/quicktime/gstqtmuxmap.h b/gst/quicktime/gstqtmuxmap.h
new file mode 100644
index 000000000..767d62a4a
--- /dev/null
+++ b/gst/quicktime/gstqtmuxmap.h
@@ -0,0 +1,83 @@
+/* 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,
+ GST_QT_MUX_FORMAT_ISML
+} GstQTMuxFormat;
+
+typedef struct _GstQTMuxFormatProp
+{
+ GstQTMuxFormat format;
+ const gchar *name;
+ const gchar *long_name;
+ const 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__ */
diff --git a/gst/qtdemux/gstrtpxqtdepay.c b/gst/quicktime/gstrtpxqtdepay.c
index 4d3a68d9d..66a9219d9 100644
--- a/gst/qtdemux/gstrtpxqtdepay.c
+++ b/gst/quicktime/gstrtpxqtdepay.c
@@ -277,7 +277,6 @@ gst_rtp_xqt_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
gint payload_len;
guint avail;
guint8 *payload;
- guint32 timestamp;
guint8 ver, pck;
gboolean s, q, l, d;
@@ -335,7 +334,9 @@ gst_rtp_xqt_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
gboolean k, f, a, z;
guint pdlen, pdpadded;
gint padding;
- guint32 media_type, timescale;
+ /* media_type only used for printing */
+ guint32 G_GNUC_UNUSED media_type;
+ guint32 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
@@ -537,7 +538,6 @@ gst_rtp_xqt_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
payload_len -= padding;
}
- timestamp = gst_rtp_buffer_get_timestamp (buf);
rtpxqtdepay->previous_id = rtpxqtdepay->current_id;
switch (pck) {
@@ -550,7 +550,7 @@ gst_rtp_xqt_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
}
case 2:
{
- guint slen, timestamp;
+ guint slen;
/* multiple samples per packet.
* 1 2 3
@@ -574,9 +574,10 @@ gst_rtp_xqt_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
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];
+ /* timestamp =
+ * (payload[4] << 24) | (payload[5] << 16) | (payload[6] << 8) |
+ * payload[7];
+ */
payload += 8;
payload_len -= 8;
diff --git a/gst/qtdemux/gstrtpxqtdepay.h b/gst/quicktime/gstrtpxqtdepay.h
index 4b8a6df8b..4b8a6df8b 100644
--- a/gst/qtdemux/gstrtpxqtdepay.h
+++ b/gst/quicktime/gstrtpxqtdepay.h
diff --git a/gst/quicktime/properties.c b/gst/quicktime/properties.c
new file mode 100644
index 000000000..8dafb2e21
--- /dev/null
+++ b/gst/quicktime/properties.c
@@ -0,0 +1,210 @@
+/* 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);
+
+/**
+ * prop_copy_fixed_size_string:
+ * @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.
+ *
+ * Copies a string of bytes without placing its size at the beginning.
+ *
+ * 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);
+}
+
+/**
+ * prop_copy_size_string:
+ *
+ * @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.
+ *
+ * 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)
+ *
+ * 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;
+}
+
+/**
+ * prop_copy_null_terminated_string:
+ * @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.
+ *
+ * Copies a string including its null terminating char to an array.
+ *
+ * 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;
+}
diff --git a/gst/quicktime/properties.h b/gst/quicktime/properties.h
new file mode 100644
index 000000000..ad67e0da0
--- /dev/null
+++ b/gst/quicktime/properties.h
@@ -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__ */
diff --git a/gst/qtdemux/qtatomparser.h b/gst/quicktime/qtatomparser.h
index 06bb3447b..06bb3447b 100644
--- a/gst/qtdemux/qtatomparser.h
+++ b/gst/quicktime/qtatomparser.h
diff --git a/gst/qtdemux/qtdemux.c b/gst/quicktime/qtdemux.c
index 4bcd7a56b..320d380b2 100644
--- a/gst/qtdemux/qtdemux.c
+++ b/gst/quicktime/qtdemux.c
@@ -4139,16 +4139,12 @@ gst_qtdemux_chain (GstPad * sinkpad, GstBuffer * inbuf)
}
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);
demux->mdatbuffer = NULL;
demux->offset = demux->mdatoffset;
@@ -6045,7 +6041,6 @@ end:
static gchar *
qtdemux_get_rtsp_uri_from_hndl (GstQTDemux * qtdemux, GNode * minf)
{
- GNode *hndl;
GNode *dinf;
GstByteReader dref;
gchar *uri = NULL;
@@ -6065,7 +6060,6 @@ qtdemux_get_rtsp_uri_from_hndl (GstQTDemux * qtdemux, GNode * minf)
gst_byte_reader_skip (&dref, 4) &&
gst_byte_reader_get_uint32_be (&dref, &dref_num_entries)) {
gint i;
- hndl = NULL;
/* search dref entries for hndl atom */
for (i = 0; i < dref_num_entries; i++) {
@@ -8706,7 +8700,9 @@ gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
break; /* Nothing special needed here */
case 0x21: /* H.264 */
codec_name = "H.264 / AVC";
- caps = gst_caps_new_simple ("video/x-h264", NULL);
+ caps = gst_caps_new_simple ("video/x-h264",
+ "stream-format", G_TYPE_STRING, "avc",
+ "alignment", G_TYPE_STRING, "au", NULL);
break;
case 0x40: /* AAC (any) */
case 0x66: /* AAC Main */
@@ -9060,7 +9056,9 @@ qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
break;
case GST_MAKE_FOURCC ('a', 'v', 'c', '1'):
_codec ("H.264 / AVC");
- caps = gst_caps_new_simple ("video/x-h264", NULL);
+ caps = gst_caps_new_simple ("video/x-h264",
+ "stream-format", G_TYPE_STRING, "avc",
+ "alignment", G_TYPE_STRING, "au", NULL);
break;
case GST_MAKE_FOURCC ('r', 'l', 'e', ' '):
_codec ("Run-length encoding");
diff --git a/gst/qtdemux/qtdemux.h b/gst/quicktime/qtdemux.h
index 069fa72eb..069fa72eb 100644
--- a/gst/qtdemux/qtdemux.h
+++ b/gst/quicktime/qtdemux.h
diff --git a/gst/qtdemux/qtdemux.vcproj b/gst/quicktime/qtdemux.vcproj
index e00260d9a..e00260d9a 100644
--- a/gst/qtdemux/qtdemux.vcproj
+++ b/gst/quicktime/qtdemux.vcproj
diff --git a/gst/qtdemux/qtdemux_dump.c b/gst/quicktime/qtdemux_dump.c
index fa6676758..fa6676758 100644
--- a/gst/qtdemux/qtdemux_dump.c
+++ b/gst/quicktime/qtdemux_dump.c
diff --git a/gst/qtdemux/qtdemux_dump.h b/gst/quicktime/qtdemux_dump.h
index 9bb1f95d4..9bb1f95d4 100644
--- a/gst/qtdemux/qtdemux_dump.h
+++ b/gst/quicktime/qtdemux_dump.h
diff --git a/gst/qtdemux/qtdemux_fourcc.h b/gst/quicktime/qtdemux_fourcc.h
index 29ad155a3..29ad155a3 100644
--- a/gst/qtdemux/qtdemux_fourcc.h
+++ b/gst/quicktime/qtdemux_fourcc.h
diff --git a/gst/qtdemux/qtdemux_lang.c b/gst/quicktime/qtdemux_lang.c
index 9a46d9075..9a46d9075 100644
--- a/gst/qtdemux/qtdemux_lang.c
+++ b/gst/quicktime/qtdemux_lang.c
diff --git a/gst/qtdemux/qtdemux_lang.h b/gst/quicktime/qtdemux_lang.h
index a5fdec0fd..a5fdec0fd 100644
--- a/gst/qtdemux/qtdemux_lang.h
+++ b/gst/quicktime/qtdemux_lang.h
diff --git a/gst/qtdemux/qtdemux_types.c b/gst/quicktime/qtdemux_types.c
index 38da35b3d..38da35b3d 100644
--- a/gst/qtdemux/qtdemux_types.c
+++ b/gst/quicktime/qtdemux_types.c
diff --git a/gst/qtdemux/qtdemux_types.h b/gst/quicktime/qtdemux_types.h
index a22efb8bf..a22efb8bf 100644
--- a/gst/qtdemux/qtdemux_types.h
+++ b/gst/quicktime/qtdemux_types.h
diff --git a/gst/qtdemux/qtpalette.h b/gst/quicktime/qtpalette.h
index 80ece2aea..80ece2aea 100644
--- a/gst/qtdemux/qtpalette.h
+++ b/gst/quicktime/qtpalette.h
diff --git a/gst/qtdemux/quicktime.c b/gst/quicktime/quicktime.c
index d567a8cf1..26df65beb 100644
--- a/gst/qtdemux/quicktime.c
+++ b/gst/quicktime/quicktime.c
@@ -26,6 +26,8 @@
#include "qtdemux.h"
#include "gstrtpxqtdepay.h"
+#include "gstqtmux.h"
+#include "gstqtmoovrecover.h"
#include <gst/pbutils/pbutils.h>
@@ -57,6 +59,11 @@ plugin_init (GstPlugin * plugin)
GST_RANK_MARGINAL, GST_TYPE_RTP_XQT_DEPAY))
return FALSE;
+ if (!gst_qt_mux_register (plugin))
+ return FALSE;
+ if (!gst_qt_moov_recover_register (plugin))
+ return FALSE;
+
return TRUE;
}
diff --git a/gst/replaygain/Makefile.am b/gst/replaygain/Makefile.am
index 7a8ac1139..0153e9fdb 100644
--- a/gst/replaygain/Makefile.am
+++ b/gst/replaygain/Makefile.am
@@ -21,3 +21,18 @@ noinst_HEADERS = \
gstrgvolume.h \
replaygain.h \
rganalysis.h
+
+
+Android.mk: Makefile.am $(BUILT_SOURCES)
+ androgenizer \
+ -:PROJECT libgstreplaygain -:SHARED libgstreplaygain \
+ -:TAGS eng debug \
+ -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
+ -:SOURCES $(libgstreplaygain_la_SOURCES) \
+ -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstreplaygain_la_CFLAGS) \
+ -:LDFLAGS $(libgstreplaygain_la_LDFLAGS) \
+ $(libgstreplaygain_la_LIBADD) \
+ -ldl \
+ -:PASSTHROUGH LOCAL_ARM_MODE:=arm \
+ LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \
+ > $@
diff --git a/gst/rtp/Makefile.am b/gst/rtp/Makefile.am
index 82ccd5fed..dcccb66ce 100644
--- a/gst/rtp/Makefile.am
+++ b/gst/rtp/Makefile.am
@@ -163,3 +163,17 @@ noinst_HEADERS = \
gstrtpvorbispay.h \
gstrtpvrawdepay.h \
gstrtpvrawpay.h
+
+Android.mk: Makefile.am $(BUILT_SOURCES)
+ androgenizer \
+ -:PROJECT libgstrtp -:SHARED libgstrtp \
+ -:TAGS eng debug \
+ -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
+ -:SOURCES $(libgstrtp_la_SOURCES) \
+ -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstrtp_la_CFLAGS) \
+ -:LDFLAGS $(libgstrtp_la_LDFLAGS) \
+ $(libgstrtp_la_LIBADD) \
+ -ldl \
+ -:PASSTHROUGH LOCAL_ARM_MODE:=arm \
+ LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \
+ > $@
diff --git a/gst/rtp/gstrtpamrdepay.c b/gst/rtp/gstrtpamrdepay.c
index f28904bdd..5a545bf8e 100644
--- a/gst/rtp/gstrtpamrdepay.c
+++ b/gst/rtp/gstrtpamrdepay.c
@@ -290,7 +290,6 @@ gst_rtp_amr_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
* no robust sorting, no interleaving data is to be depayloaded */
{
guint8 *payload, *p, *dp;
- guint8 CMR;
gint i, num_packets, num_nonempty_packets;
gint amr_len;
gint ILL, ILP;
@@ -311,7 +310,7 @@ gst_rtp_amr_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
* | CMR |R|R|R|R|
* +-+-+-+-+-+-+-+-+
*/
- CMR = (payload[0] & 0xf0) >> 4;
+ /* CMR = (payload[0] & 0xf0) >> 4; */
/* strip CMR header now, pack FT and the data for the decoder */
payload_len -= 1;
diff --git a/gst/rtp/gstrtpbvdepay.c b/gst/rtp/gstrtpbvdepay.c
index 7d5cdf362..7133f8e45 100644
--- a/gst/rtp/gstrtpbvdepay.c
+++ b/gst/rtp/gstrtpbvdepay.c
@@ -75,10 +75,8 @@ gst_rtp_bv_depay_base_init (gpointer klass)
static void
gst_rtp_bv_depay_class_init (GstRTPBVDepayClass * klass)
{
- GObjectClass *gobject_class;
GstBaseRTPDepayloadClass *gstbasertpdepayload_class;
- gobject_class = (GObjectClass *) klass;
gstbasertpdepayload_class = (GstBaseRTPDepayloadClass *) klass;
gstbasertpdepayload_class->process = gst_rtp_bv_depay_process;
diff --git a/gst/rtp/gstrtpbvpay.c b/gst/rtp/gstrtpbvpay.c
index 7ddc5781c..0c0100105 100644
--- a/gst/rtp/gstrtpbvpay.c
+++ b/gst/rtp/gstrtpbvpay.c
@@ -93,10 +93,8 @@ gst_rtp_bv_pay_class_init (GstRTPBVPayClass * klass)
static void
gst_rtp_bv_pay_init (GstRTPBVPay * rtpbvpay, GstRTPBVPayClass * klass)
{
- GstBaseRTPPayload *basertppayload;
GstBaseRTPAudioPayload *basertpaudiopayload;
- basertppayload = GST_BASE_RTP_PAYLOAD (rtpbvpay);
basertpaudiopayload = GST_BASE_RTP_AUDIO_PAYLOAD (rtpbvpay);
rtpbvpay->mode = -1;
diff --git a/gst/rtp/gstrtpg722pay.c b/gst/rtp/gstrtpg722pay.c
index 7346ca149..29cd22a64 100644
--- a/gst/rtp/gstrtpg722pay.c
+++ b/gst/rtp/gstrtpg722pay.c
@@ -190,10 +190,6 @@ gst_rtp_g722_pay_getcaps (GstBaseRTPPayload * rtppayload, GstPad * pad)
if (otherpadcaps) {
if (!gst_caps_is_empty (otherpadcaps)) {
- GstStructure *structure;
-
- structure = gst_caps_get_structure (otherpadcaps, 0);
-
gst_caps_set_simple (caps, "channels", G_TYPE_INT, 1, NULL);
gst_caps_set_simple (caps, "rate", G_TYPE_INT, 16000, NULL);
}
diff --git a/gst/rtp/gstrtpgsmpay.c b/gst/rtp/gstrtpgsmpay.c
index ad984bcde..479013e13 100644
--- a/gst/rtp/gstrtpgsmpay.c
+++ b/gst/rtp/gstrtpgsmpay.c
@@ -143,9 +143,15 @@ gst_rtp_gsm_pay_handle_buffer (GstBaseRTPPayload * basepayload,
/* FIXME, only one GSM frame per RTP packet for now */
payload_len = size;
+ /* FIXME, just error out for now */
+ if (payload_len > GST_BASE_RTP_PAYLOAD_MTU (rtpgsmpay)) {
+ GST_ELEMENT_ERROR (rtpgsmpay, STREAM, ENCODE, (NULL),
+ ("payload_len %u > mtu %u", payload_len,
+ GST_BASE_RTP_PAYLOAD_MTU (rtpgsmpay)));
+ return GST_FLOW_ERROR;
+ }
+
outbuf = gst_rtp_buffer_new_allocate (payload_len, 0, 0);
- /* FIXME, assert for now */
- g_assert (payload_len <= GST_BASE_RTP_PAYLOAD_MTU (rtpgsmpay));
/* copy timestamp and duration */
GST_BUFFER_TIMESTAMP (outbuf) = timestamp;
diff --git a/gst/rtp/gstrtpgstdepay.c b/gst/rtp/gstrtpgstdepay.c
index 4e536bafa..6dc5e511a 100644
--- a/gst/rtp/gstrtpgstdepay.c
+++ b/gst/rtp/gstrtpgstdepay.c
@@ -183,7 +183,6 @@ gst_rtp_gst_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
GstBuffer *subbuf, *outbuf = NULL;
gint payload_len;
guint8 *payload;
- guint16 frag_offset;
guint CV;
rtpgstdepay = GST_RTP_GST_DEPAY (depayload);
@@ -210,8 +209,9 @@ gst_rtp_gst_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
* | Frag_offset |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
- frag_offset =
- (payload[4] << 24) | (payload[5] << 16) | (payload[6] << 8) | payload[7];
+ /* frag_offset =
+ * (payload[4] << 24) | (payload[5] << 16) | (payload[6] << 8) | payload[7];
+ */
/* subbuffer skipping the 8 header bytes */
subbuf = gst_rtp_buffer_get_payload_subbuffer (buf, 8, -1);
diff --git a/gst/rtp/gstrtpgstpay.c b/gst/rtp/gstrtpgstpay.c
index 3e1aaad9d..dfdd95404 100644
--- a/gst/rtp/gstrtpgstpay.c
+++ b/gst/rtp/gstrtpgstpay.c
@@ -68,8 +68,6 @@ GST_STATIC_PAD_TEMPLATE ("src",
"clock-rate = (int) 90000, " "encoding-name = (string) \"X-GST\"")
);
-static void gst_rtp_gst_pay_finalize (GObject * object);
-
static gboolean gst_rtp_gst_pay_setcaps (GstBaseRTPPayload * payload,
GstCaps * caps);
static GstFlowReturn gst_rtp_gst_pay_handle_buffer (GstBaseRTPPayload * payload,
@@ -96,14 +94,10 @@ GST_BOILERPLATE (GstRtpGSTPay, gst_rtp_gst_pay, GstBaseRTPPayload,
static void
gst_rtp_gst_pay_class_init (GstRtpGSTPayClass * klass)
{
- GObjectClass *gobject_class;
GstBaseRTPPayloadClass *gstbasertppayload_class;
- gobject_class = (GObjectClass *) klass;
gstbasertppayload_class = (GstBaseRTPPayloadClass *) klass;
- gobject_class->finalize = gst_rtp_gst_pay_finalize;
-
gstbasertppayload_class->set_caps = gst_rtp_gst_pay_setcaps;
gstbasertppayload_class->handle_buffer = gst_rtp_gst_pay_handle_buffer;
}
@@ -113,16 +107,6 @@ gst_rtp_gst_pay_init (GstRtpGSTPay * rtpgstpay, GstRtpGSTPayClass * klass)
{
}
-static void
-gst_rtp_gst_pay_finalize (GObject * object)
-{
- GstRtpGSTPay *rtpgstpay;
-
- rtpgstpay = GST_RTP_GST_PAY (object);
-
- G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
static gboolean
gst_rtp_gst_pay_setcaps (GstBaseRTPPayload * payload, GstCaps * caps)
{
@@ -152,7 +136,7 @@ gst_rtp_gst_pay_handle_buffer (GstBaseRTPPayload * basepayload,
GstBuffer *outbuf;
GstFlowReturn ret;
GstClockTime timestamp;
- guint16 frag_offset;
+ guint32 frag_offset;
guint flags;
rtpgstpay = GST_RTP_GST_PAY (basepayload);
diff --git a/gst/rtp/gstrtpj2kpay.c b/gst/rtp/gstrtpj2kpay.c
index 3734534f8..782cf229f 100644
--- a/gst/rtp/gstrtpj2kpay.c
+++ b/gst/rtp/gstrtpj2kpay.c
@@ -134,11 +134,9 @@ static void
gst_rtp_j2k_pay_class_init (GstRtpJ2KPayClass * klass)
{
GObjectClass *gobject_class;
- GstElementClass *gstelement_class;
GstBaseRTPPayloadClass *gstbasertppayload_class;
gobject_class = (GObjectClass *) klass;
- gstelement_class = (GstElementClass *) klass;
gstbasertppayload_class = (GstBaseRTPPayloadClass *) klass;
gobject_class->set_property = gst_rtp_j2k_pay_set_property;
diff --git a/gst/rtp/gstrtpmp4gpay.c b/gst/rtp/gstrtpmp4gpay.c
index c09506406..b3a69662c 100644
--- a/gst/rtp/gstrtpmp4gpay.c
+++ b/gst/rtp/gstrtpmp4gpay.c
@@ -451,11 +451,8 @@ gst_rtp_mp4g_pay_flush (GstRtpMP4GPay * rtpmp4gpay)
guint avail, total;
GstBuffer *outbuf;
GstFlowReturn ret;
- gboolean fragmented;
guint mtu;
- fragmented = FALSE;
-
/* the data available in the adapter is either smaller
* than the MTU or bigger. In the case it is smaller, the complete
* adapter contents can be put in one packet. In the case the
@@ -544,7 +541,6 @@ gst_rtp_mp4g_pay_flush (GstRtpMP4GPay * rtpmp4gpay)
ret = gst_basertppayload_push (GST_BASE_RTP_PAYLOAD (rtpmp4gpay), outbuf);
avail -= payload_len;
- fragmented = TRUE;
}
return ret;
diff --git a/gst/rtp/gstrtpmp4vpay.c b/gst/rtp/gstrtpmp4vpay.c
index 811e1b4a5..568bd835c 100644
--- a/gst/rtp/gstrtpmp4vpay.c
+++ b/gst/rtp/gstrtpmp4vpay.c
@@ -141,8 +141,6 @@ gst_rtp_mp4v_pay_class_init (GstRtpMP4VPayClass * klass)
static void
gst_rtp_mp4v_pay_init (GstRtpMP4VPay * rtpmp4vpay, GstRtpMP4VPayClass * klass)
{
- GstPad *sinkpad;
-
rtpmp4vpay->adapter = gst_adapter_new ();
rtpmp4vpay->rate = 90000;
rtpmp4vpay->profile = 1;
@@ -153,8 +151,6 @@ gst_rtp_mp4v_pay_init (GstRtpMP4VPay * rtpmp4vpay, GstRtpMP4VPayClass * klass)
rtpmp4vpay->last_config = -1;
rtpmp4vpay->config = NULL;
-
- sinkpad = GST_BASE_RTP_PAYLOAD_SINKPAD (rtpmp4vpay);
}
static void
diff --git a/gst/rtp/gstrtpmpadepay.c b/gst/rtp/gstrtpmpadepay.c
index a76a7f39e..1fdc8d449 100644
--- a/gst/rtp/gstrtpmpadepay.c
+++ b/gst/rtp/gstrtpmpadepay.c
@@ -127,8 +127,6 @@ gst_rtp_mpa_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
{
gint payload_len;
- guint8 *payload;
- guint16 frag_offset;
gboolean marker;
payload_len = gst_rtp_buffer_get_payload_len (buf);
@@ -136,7 +134,6 @@ gst_rtp_mpa_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
if (payload_len <= 4)
goto empty_packet;
- payload = gst_rtp_buffer_get_payload (buf);
/* strip off header
*
* 0 1 2 3
@@ -145,7 +142,7 @@ gst_rtp_mpa_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
* | MBZ | Frag_offset |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
- frag_offset = (payload[2] << 8) | payload[3];
+ /* frag_offset = (payload[2] << 8) | payload[3]; */
/* subbuffer skipping the 4 header bytes */
outbuf = gst_rtp_buffer_get_payload_subbuffer (buf, 4, -1);
diff --git a/gst/rtp/gstrtpqcelpdepay.c b/gst/rtp/gstrtpqcelpdepay.c
index badeb9f24..7949ae780 100644
--- a/gst/rtp/gstrtpqcelpdepay.c
+++ b/gst/rtp/gstrtpqcelpdepay.c
@@ -118,7 +118,7 @@ static void
gst_rtp_qcelp_depay_init (GstRtpQCELPDepay * rtpqcelpdepay,
GstRtpQCELPDepayClass * klass)
{
- GstBaseRTPDepayload *depayload;
+ GstBaseRTPDepayload G_GNUC_UNUSED *depayload;
depayload = GST_BASE_RTP_DEPAYLOAD (rtpqcelpdepay);
}
@@ -144,11 +144,8 @@ static gboolean
gst_rtp_qcelp_depay_setcaps (GstBaseRTPDepayload * depayload, GstCaps * caps)
{
GstCaps *srccaps;
- GstRtpQCELPDepay *rtpqcelpdepay;
gboolean res;
- rtpqcelpdepay = GST_RTP_QCELP_DEPAY (depayload);
-
srccaps = gst_caps_new_simple ("audio/qcelp",
"channels", G_TYPE_INT, 1, "rate", G_TYPE_INT, 8000, NULL);
res = gst_pad_set_caps (GST_BASE_RTP_DEPAYLOAD_SRCPAD (depayload), srccaps);
@@ -263,7 +260,7 @@ gst_rtp_qcelp_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
GstClockTime timestamp;
guint payload_len, offset, index;
guint8 *payload;
- guint RR, LLL, NNN;
+ guint LLL, NNN;
depay = GST_RTP_QCELP_DEPAY (depayload);
@@ -281,7 +278,7 @@ gst_rtp_qcelp_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
* |RR | LLL | NNN |
* +-+-+-+-+-+-+-+-+
*/
- RR = payload[0] >> 6;
+ /* RR = payload[0] >> 6; */
LLL = (payload[0] & 0x38) >> 3;
NNN = (payload[0] & 0x07);
diff --git a/gst/rtp/gstrtpspeexpay.c b/gst/rtp/gstrtpspeexpay.c
index a551fa943..35273e25a 100644
--- a/gst/rtp/gstrtpspeexpay.c
+++ b/gst/rtp/gstrtpspeexpay.c
@@ -260,6 +260,11 @@ gst_rtp_speex_pay_handle_buffer (GstBaseRTPPayload * basepayload,
break;
}
+ if (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_GAP)) {
+ ret = GST_FLOW_OK;
+ goto done;
+ }
+
timestamp = GST_BUFFER_TIMESTAMP (buffer);
duration = GST_BUFFER_DURATION (buffer);
diff --git a/gst/rtpmanager/Makefile.am b/gst/rtpmanager/Makefile.am
index 10e2d62f6..f61099c1b 100644
--- a/gst/rtpmanager/Makefile.am
+++ b/gst/rtpmanager/Makefile.am
@@ -48,3 +48,17 @@ CLEANFILES = $(BUILT_SOURCES)
EXTRA_DIST = gstrtpbin-marshal.list
+Android.mk: Makefile.am $(BUILT_SOURCES)
+ androgenizer \
+ -:PROJECT libgstrtpmanager -:SHARED libgstrtpmanager \
+ -:TAGS eng debug \
+ -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
+ -:SOURCES $(libgstrtpmanager_la_SOURCES) \
+ $(nodist_libgstrtpmanager_la_SOURCES) \
+ -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstrtpmanager_la_CFLAGS) \
+ -:LDFLAGS $(libgstrtpmanager_la_LDFLAGS) \
+ $(libgstrtpmanager_la_LIBADD) \
+ -ldl \
+ -:PASSTHROUGH LOCAL_ARM_MODE:=arm \
+ LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \
+ > $@
diff --git a/gst/rtpmanager/gstrtpbin-marshal.list b/gst/rtpmanager/gstrtpbin-marshal.list
index 7d9821f51..6606a4255 100644
--- a/gst/rtpmanager/gstrtpbin-marshal.list
+++ b/gst/rtpmanager/gstrtpbin-marshal.list
@@ -7,6 +7,4 @@ VOID:UINT
VOID:UINT,UINT
VOID:OBJECT,OBJECT
UINT64:BOOL,UINT64
-BOOL:POINTER,BOOL
-VOID:UINT,UINT,UINT,UINT,POINTER
VOID:UINT64
diff --git a/gst/rtpmanager/gstrtpjitterbuffer.c b/gst/rtpmanager/gstrtpjitterbuffer.c
index 861e1e3dd..e11869985 100644
--- a/gst/rtpmanager/gstrtpjitterbuffer.c
+++ b/gst/rtpmanager/gstrtpjitterbuffer.c
@@ -1008,6 +1008,10 @@ gst_rtp_jitter_buffer_src_event (GstPad * pad, GstEvent * event)
GstRtpJitterBufferPrivate *priv;
jitterbuffer = GST_RTP_JITTER_BUFFER (gst_pad_get_parent (pad));
+ if (G_UNLIKELY (jitterbuffer == NULL)) {
+ gst_event_unref (event);
+ return FALSE;
+ }
priv = jitterbuffer->priv;
GST_DEBUG_OBJECT (jitterbuffer, "received %s", GST_EVENT_TYPE_NAME (event));
@@ -1049,6 +1053,10 @@ gst_rtp_jitter_buffer_sink_event (GstPad * pad, GstEvent * event)
GstRtpJitterBufferPrivate *priv;
jitterbuffer = GST_RTP_JITTER_BUFFER (gst_pad_get_parent (pad));
+ if (G_UNLIKELY (jitterbuffer == NULL)) {
+ gst_event_unref (event);
+ return FALSE;
+ }
priv = jitterbuffer->priv;
GST_DEBUG_OBJECT (jitterbuffer, "received %s", GST_EVENT_TYPE_NAME (event));
@@ -1136,10 +1144,8 @@ static gboolean
gst_rtp_jitter_buffer_sink_rtcp_event (GstPad * pad, GstEvent * event)
{
GstRtpJitterBuffer *jitterbuffer;
- GstRtpJitterBufferPrivate *priv;
jitterbuffer = GST_RTP_JITTER_BUFFER (gst_pad_get_parent (pad));
- priv = jitterbuffer->priv;
GST_DEBUG_OBJECT (jitterbuffer, "received %s", GST_EVENT_TYPE_NAME (event));
@@ -2076,6 +2082,8 @@ gst_rtp_jitter_buffer_query (GstPad * pad, GstQuery * query)
gboolean res = FALSE;
jitterbuffer = GST_RTP_JITTER_BUFFER (gst_pad_get_parent (pad));
+ if (G_UNLIKELY (jitterbuffer == NULL))
+ return FALSE;
priv = jitterbuffer->priv;
switch (GST_QUERY_TYPE (query)) {
diff --git a/gst/rtpmanager/gstrtpptdemux.c b/gst/rtpmanager/gstrtpptdemux.c
index 78c4956d3..3c0004dbb 100644
--- a/gst/rtpmanager/gstrtpptdemux.c
+++ b/gst/rtpmanager/gstrtpptdemux.c
@@ -434,6 +434,10 @@ gst_rtp_pt_demux_sink_event (GstPad * pad, GstEvent * event)
gboolean res = FALSE;
rtpdemux = GST_RTP_PT_DEMUX (gst_pad_get_parent (pad));
+ if (G_UNLIKELY (rtpdemux == NULL)) {
+ gst_event_unref (event);
+ return FALSE;
+ }
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_CUSTOM_DOWNSTREAM:
diff --git a/gst/rtpmanager/gstrtpsession.c b/gst/rtpmanager/gstrtpsession.c
index 64abc94ba..986b81a4d 100644
--- a/gst/rtpmanager/gstrtpsession.c
+++ b/gst/rtpmanager/gstrtpsession.c
@@ -1325,6 +1325,10 @@ gst_rtp_session_event_recv_rtp_sink (GstPad * pad, GstEvent * event)
gboolean ret = FALSE;
rtpsession = GST_RTP_SESSION (gst_pad_get_parent (pad));
+ if (G_UNLIKELY (rtpsession == NULL)) {
+ gst_event_unref (event);
+ return FALSE;
+ }
GST_DEBUG_OBJECT (rtpsession, "received event %s",
GST_EVENT_TYPE_NAME (event));
@@ -1432,6 +1436,10 @@ gst_rtp_session_event_recv_rtp_src (GstPad * pad, GstEvent * event)
guint pt;
rtpsession = GST_RTP_SESSION (gst_pad_get_parent (pad));
+ if (G_UNLIKELY (rtpsession == NULL)) {
+ gst_event_unref (event);
+ return FALSE;
+ }
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_CUSTOM_UPSTREAM:
@@ -1465,22 +1473,29 @@ gst_rtp_session_iterate_internal_links (GstPad * pad)
{
GstRtpSession *rtpsession;
GstPad *otherpad = NULL;
- GstIterator *it;
+ GstIterator *it = NULL;
rtpsession = GST_RTP_SESSION (gst_pad_get_parent (pad));
+ if (G_UNLIKELY (rtpsession == NULL))
+ return NULL;
+ GST_RTP_SESSION_LOCK (rtpsession);
if (pad == rtpsession->recv_rtp_src) {
- otherpad = rtpsession->recv_rtp_sink;
+ otherpad = gst_object_ref (rtpsession->recv_rtp_sink);
} else if (pad == rtpsession->recv_rtp_sink) {
- otherpad = rtpsession->recv_rtp_src;
+ otherpad = gst_object_ref (rtpsession->recv_rtp_src);
} else if (pad == rtpsession->send_rtp_src) {
- otherpad = rtpsession->send_rtp_sink;
+ otherpad = gst_object_ref (rtpsession->send_rtp_sink);
} else if (pad == rtpsession->send_rtp_sink) {
- otherpad = rtpsession->send_rtp_src;
+ otherpad = gst_object_ref (rtpsession->send_rtp_src);
}
+ GST_RTP_SESSION_UNLOCK (rtpsession);
- it = gst_iterator_new_single (GST_TYPE_PAD, otherpad,
- (GstCopyFunction) gst_object_ref, (GFreeFunc) gst_object_unref);
+ if (otherpad) {
+ it = gst_iterator_new_single (GST_TYPE_PAD, otherpad,
+ (GstCopyFunction) gst_object_ref, (GFreeFunc) gst_object_unref);
+ gst_object_unref (otherpad);
+ }
gst_object_unref (rtpsession);
@@ -1582,7 +1597,6 @@ gst_rtp_session_chain_recv_rtcp (GstPad * pad, GstBuffer * buffer)
GstRtpSessionPrivate *priv;
GstClockTime current_time;
guint64 ntpnstime;
- GstFlowReturn ret;
rtpsession = GST_RTP_SESSION (gst_pad_get_parent (pad));
priv = rtpsession->priv;
@@ -1592,12 +1606,11 @@ gst_rtp_session_chain_recv_rtcp (GstPad * pad, GstBuffer * buffer)
current_time = gst_clock_get_time (priv->sysclock);
get_current_times (rtpsession, NULL, &ntpnstime);
- ret =
- rtp_session_process_rtcp (priv->session, buffer, current_time, ntpnstime);
+ rtp_session_process_rtcp (priv->session, buffer, current_time, ntpnstime);
gst_object_unref (rtpsession);
- return GST_FLOW_OK;
+ return GST_FLOW_OK; /* always return OK */
}
static gboolean
@@ -1630,10 +1643,13 @@ static gboolean
gst_rtp_session_event_send_rtcp_src (GstPad * pad, GstEvent * event)
{
GstRtpSession *rtpsession;
- gboolean ret;
+ gboolean ret = TRUE;
rtpsession = GST_RTP_SESSION (gst_pad_get_parent (pad));
-
+ if (G_UNLIKELY (rtpsession == NULL)) {
+ gst_event_unref (event);
+ return FALSE;
+ }
GST_DEBUG_OBJECT (rtpsession, "received EVENT");
switch (GST_EVENT_TYPE (event)) {
@@ -1650,7 +1666,6 @@ gst_rtp_session_event_send_rtcp_src (GstPad * pad, GstEvent * event)
}
gst_object_unref (rtpsession);
-
return ret;
}
@@ -1713,9 +1728,21 @@ gst_rtp_session_event_send_rtp_sink (GstPad * pad, GstEvent * event)
current_time);
break;
}
- default:
- ret = gst_pad_push_event (rtpsession->send_rtp_src, event);
+ default:{
+ GstPad *send_rtp_src = NULL;
+ GST_RTP_SESSION_LOCK (rtpsession);
+ if (rtpsession->send_rtp_src)
+ send_rtp_src = gst_object_ref (rtpsession->send_rtp_src);
+ GST_RTP_SESSION_UNLOCK (rtpsession);
+
+ if (send_rtp_src) {
+ ret = gst_pad_push_event (send_rtp_src, event);
+ gst_object_unref (send_rtp_src);
+ } else
+ gst_event_unref (event);
+
break;
+ }
}
gst_object_unref (rtpsession);
diff --git a/gst/rtpmanager/gstrtpssrcdemux.c b/gst/rtpmanager/gstrtpssrcdemux.c
index 65d447520..2688775e7 100644
--- a/gst/rtpmanager/gstrtpssrcdemux.c
+++ b/gst/rtpmanager/gstrtpssrcdemux.c
@@ -383,8 +383,10 @@ gst_rtp_ssrc_demux_clear_ssrc (GstRtpSsrcDemux * demux, guint32 ssrc)
GST_PAD_LOCK (demux);
dpad = find_demux_pad_for_ssrc (demux, ssrc);
- if (dpad == NULL)
+ if (dpad == NULL) {
+ GST_PAD_UNLOCK (demux);
goto unknown_pad;
+ }
GST_DEBUG_OBJECT (demux, "clearing pad for SSRC %08x", ssrc);
@@ -408,7 +410,7 @@ gst_rtp_ssrc_demux_clear_ssrc (GstRtpSsrcDemux * demux, guint32 ssrc)
/* ERRORS */
unknown_pad:
{
- g_warning ("unknown SSRC %08x", ssrc);
+ GST_WARNING_OBJECT (demux, "unknown SSRC %08x", ssrc);
return;
}
}
@@ -420,6 +422,10 @@ gst_rtp_ssrc_demux_sink_event (GstPad * pad, GstEvent * event)
gboolean res = FALSE;
demux = GST_RTP_SSRC_DEMUX (gst_pad_get_parent (pad));
+ if (G_UNLIKELY (demux == NULL)) {
+ gst_event_unref (event);
+ return FALSE;
+ }
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_FLUSH_STOP:
@@ -699,6 +705,8 @@ gst_rtp_ssrc_demux_src_query (GstPad * pad, GstQuery * query)
gboolean res = FALSE;
demux = GST_RTP_SSRC_DEMUX (gst_pad_get_parent (pad));
+ if (G_UNLIKELY (demux == NULL))
+ return FALSE;
switch (GST_QUERY_TYPE (query)) {
case GST_QUERY_LATENCY:
diff --git a/gst/rtpmanager/rtpsession.c b/gst/rtpmanager/rtpsession.c
index aff14eb0a..13b15f4d5 100644
--- a/gst/rtpmanager/rtpsession.c
+++ b/gst/rtpmanager/rtpsession.c
@@ -131,6 +131,75 @@ accumulate_trues (GSignalInvocationHint * ihint, GValue * return_accu,
}
static void
+gst_rtp_bin_marshal_BOOLEAN__MINIOBJECT_BOOLEAN (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__MINIOBJECT_BOOLEAN) (gpointer data1,
+ gpointer arg_1, gboolean arg_2, gpointer data2);
+ register GMarshalFunc_BOOLEAN__MINIOBJECT_BOOLEAN callback;
+ register GCClosure *cc = (GCClosure *) closure;
+ register gpointer data1, data2;
+ gboolean 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_BOOLEAN__MINIOBJECT_BOOLEAN) (marshal_data ? marshal_data :
+ cc->callback);
+
+ v_return = callback (data1,
+ gst_value_get_mini_object (param_values + 1),
+ g_value_get_boolean (param_values + 2), data2);
+
+ g_value_set_boolean (return_value, v_return);
+}
+
+static void
+gst_rtp_bin_marshal_VOID__UINT_UINT_UINT_UINT_MINIOBJECT (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__UINT_UINT_UINT_UINT_MINIOBJECT) (gpointer
+ data1, guint arg_1, guint arg_2, guint arg_3, guint arg_4, gpointer arg_5,
+ gpointer data2);
+ register GMarshalFunc_VOID__UINT_UINT_UINT_UINT_MINIOBJECT callback;
+ register GCClosure *cc = (GCClosure *) closure;
+ register gpointer data1, data2;
+
+ g_return_if_fail (n_param_values == 6);
+
+ 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__UINT_UINT_UINT_UINT_MINIOBJECT) (marshal_data ?
+ marshal_data : cc->callback);
+
+ callback (data1,
+ g_value_get_uint (param_values + 1),
+ g_value_get_uint (param_values + 2),
+ g_value_get_uint (param_values + 3),
+ g_value_get_uint (param_values + 4),
+ gst_value_get_mini_object (param_values + 5), data2);
+}
+
+
+static void
rtp_session_class_init (RTPSessionClass * klass)
{
GObjectClass *gobject_class;
@@ -278,8 +347,8 @@ rtp_session_class_init (RTPSessionClass * klass)
rtp_session_signals[SIGNAL_ON_SENDING_RTCP] =
g_signal_new ("on-sending-rtcp", G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (RTPSessionClass, on_sending_rtcp),
- accumulate_trues, NULL, gst_rtp_bin_marshal_BOOLEAN__POINTER_BOOLEAN,
- G_TYPE_BOOLEAN, 2, G_TYPE_POINTER, G_TYPE_BOOLEAN);
+ accumulate_trues, NULL, gst_rtp_bin_marshal_BOOLEAN__MINIOBJECT_BOOLEAN,
+ G_TYPE_BOOLEAN, 2, GST_TYPE_BUFFER, G_TYPE_BOOLEAN);
/**
* RTPSession::on-feedback-rtcp:
@@ -298,9 +367,9 @@ rtp_session_class_init (RTPSessionClass * klass)
rtp_session_signals[SIGNAL_ON_FEEDBACK_RTCP] =
g_signal_new ("on-feedback-rtcp", G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (RTPSessionClass, on_feedback_rtcp),
- NULL, NULL, gst_rtp_bin_marshal_VOID__UINT_UINT_UINT_UINT_POINTER,
+ NULL, NULL, gst_rtp_bin_marshal_VOID__UINT_UINT_UINT_UINT_MINIOBJECT,
G_TYPE_NONE, 4, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT,
- G_TYPE_POINTER);
+ GST_TYPE_BUFFER);
/**
* RTPSession::send-rtcp:
@@ -1942,10 +2011,16 @@ rtp_session_process_sdes (RTPSession * sess, GstRTCPPacket * packet,
validated = !RTP_SOURCE_IS_ACTIVE (source);
source->validated = TRUE;
+ /* source became active */
+ if (validated) {
+ sess->stats.active_sources++;
+ GST_DEBUG ("source: %08x became active, %d active sources", ssrc,
+ sess->stats.active_sources);
+ on_ssrc_validated (sess, source);
+ }
+
if (created)
on_new_ssrc (sess, source);
- if (validated)
- on_ssrc_validated (sess, source);
if (changed)
on_ssrc_sdes (sess, source);
@@ -1979,6 +2054,9 @@ rtp_session_process_bye (RTPSession * sess, GstRTCPPacket * packet,
ssrc = gst_rtcp_packet_bye_get_nth_ssrc (packet, i);
GST_DEBUG ("SSRC: %08x", ssrc);
+ if (ssrc == sess->source->ssrc)
+ return;
+
/* find src and mark bye, no probation when dealing with RTCP */
source = obtain_source (sess, ssrc, &created, arrival, FALSE);
if (!source)
@@ -2102,27 +2180,29 @@ rtp_session_process_feedback (RTPSession * sess, GstRTCPPacket * packet,
GstRTCPFBType fbtype = gst_rtcp_packet_fb_get_type (packet);
guint32 sender_ssrc = gst_rtcp_packet_fb_get_sender_ssrc (packet);
guint32 media_ssrc = gst_rtcp_packet_fb_get_media_ssrc (packet);
- guint length = 4 * (gst_rtcp_packet_get_length (packet) - 2);
+ guint8 *fci_data = gst_rtcp_packet_fb_get_fci (packet);
+ guint fci_length = 4 * gst_rtcp_packet_fb_get_fci_length (packet);
- GST_DEBUG ("received feedback %d:%d from %08X about %08X"
- " with FCI of length %d", type, fbtype, sender_ssrc, media_ssrc, length);
+ GST_DEBUG ("received feedback %d:%d from %08X about %08X with FCI of "
+ "length %d", type, fbtype, sender_ssrc, media_ssrc, fci_length);
if (g_signal_has_handler_pending (sess,
rtp_session_signals[SIGNAL_ON_FEEDBACK_RTCP], 0, TRUE)) {
- GstBuffer *fci = NULL;
+ GstBuffer *fci_buffer = NULL;
- if (length) {
- fci = gst_buffer_create_sub (packet->buffer, packet->offset + 72, length);
- GST_BUFFER_TIMESTAMP (fci) = arrival->running_time;
+ if (fci_length > 0) {
+ fci_buffer = gst_buffer_create_sub (packet->buffer,
+ fci_data - GST_BUFFER_DATA (packet->buffer), fci_length);
+ GST_BUFFER_TIMESTAMP (fci_buffer) = arrival->running_time;
}
RTP_SESSION_UNLOCK (sess);
g_signal_emit (sess, rtp_session_signals[SIGNAL_ON_FEEDBACK_RTCP], 0,
- type, fbtype, sender_ssrc, media_ssrc, fci);
+ type, fbtype, sender_ssrc, media_ssrc, fci_buffer);
RTP_SESSION_LOCK (sess);
- if (fci)
- gst_buffer_unref (fci);
+ if (fci_buffer)
+ gst_buffer_unref (fci_buffer);
}
if (sess->rtcp_feedback_retention_window) {
diff --git a/gst/rtsp/Makefile.am b/gst/rtsp/Makefile.am
index 914148130..8e65ced40 100644
--- a/gst/rtsp/Makefile.am
+++ b/gst/rtsp/Makefile.am
@@ -15,3 +15,17 @@ noinst_HEADERS = gstrtspsrc.h \
gstrtsp.h \
gstrtpdec.h \
gstrtspext.h
+
+Android.mk: Makefile.am $(BUILT_SOURCES)
+ androgenizer \
+ -:PROJECT libgstrtsp -:SHARED libgstrtsp \
+ -:TAGS eng debug \
+ -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
+ -:SOURCES $(libgstrtsp_la_SOURCES) \
+ -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstrtsp_la_CFLAGS) \
+ -:LDFLAGS $(libgstrtsp_la_LDFLAGS) \
+ $(libgstrtsp_la_LIBADD) \
+ -ldl \
+ -:PASSTHROUGH LOCAL_ARM_MODE:=arm \
+ LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \
+ > $@
diff --git a/gst/shapewipe/Makefile.am b/gst/shapewipe/Makefile.am
index 7f6df3726..35cf5df03 100644
--- a/gst/shapewipe/Makefile.am
+++ b/gst/shapewipe/Makefile.am
@@ -9,3 +9,17 @@ libgstshapewipe_la_LIBTOOLFLAGS = --tag=disable-static
noinst_HEADERS = gstshapewipe.h
+
+Android.mk: Makefile.am $(BUILT_SOURCES)
+ androgenizer \
+ -:PROJECT libgstshapewhipe -:SHARED libgstshapewhipe \
+ -:TAGS eng debug \
+ -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
+ -:SOURCES $(libgstshapewhipe_la_SOURCES) \
+ -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstshapewhipe_la_CFLAGS) \
+ -:LDFLAGS $(libgstshapewhipe_la_LDFLAGS) \
+ $(libgstshapewhipe_la_LIBADD) \
+ -ldl \
+ -:PASSTHROUGH LOCAL_ARM_MODE:=arm \
+ LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \
+ > $@
diff --git a/gst/shapewipe/gstshapewipe.c b/gst/shapewipe/gstshapewipe.c
index 49e0736a9..83005a0c0 100644
--- a/gst/shapewipe/gstshapewipe.c
+++ b/gst/shapewipe/gstshapewipe.c
@@ -824,7 +824,7 @@ gst_shape_wipe_blend_##name##_##depth (GstShapeWipe * self, GstBuffer * inbuf, \
gfloat position = self->mask_position; \
gfloat low = position - (self->mask_border / 2.0f); \
gfloat high = position + (self->mask_border / 2.0f); \
- guint32 low_i, high_i, position_i, round_i; \
+ guint32 low_i, high_i, round_i; \
gint width = self->width, height = self->height; \
\
if (low < 0.0f) { \
@@ -837,7 +837,6 @@ gst_shape_wipe_blend_##name##_##depth (GstShapeWipe * self, GstBuffer * inbuf, \
high = 1.0f; \
} \
\
- position_i = position * 65536; \
low_i = low * 65536; \
high_i = high * 65536; \
round_i = (high_i - low_i) >> 1; \
diff --git a/gst/smpte/Makefile.am b/gst/smpte/Makefile.am
index 0a0608fcc..34bb039a0 100644
--- a/gst/smpte/Makefile.am
+++ b/gst/smpte/Makefile.am
@@ -11,3 +11,16 @@ libgstsmpte_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) $(GST_BASE_LIBS) $(LIBM) \
libgstsmpte_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
libgstsmpte_la_LIBTOOLFLAGS = --tag=disable-static
+Android.mk: Makefile.am $(BUILT_SOURCES)
+ androgenizer \
+ -:PROJECT libgstsmpte -:SHARED libgstsmpte \
+ -:TAGS eng debug \
+ -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
+ -:SOURCES $(libgstsmpte_la_SOURCES) \
+ -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstsmpte_la_CFLAGS) \
+ -:LDFLAGS $(libgstsmpte_la_LDFLAGS) \
+ $(libgstsmpte_la_LIBADD) \
+ -ldl \
+ -:PASSTHROUGH LOCAL_ARM_MODE:=arm \
+ LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \
+ > $@
diff --git a/gst/spectrum/Makefile.am b/gst/spectrum/Makefile.am
index 4286608e8..99c438415 100644
--- a/gst/spectrum/Makefile.am
+++ b/gst/spectrum/Makefile.am
@@ -10,3 +10,18 @@ libgstspectrum_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
libgstspectrum_la_LIBTOOLFLAGS = --tag=disable-static
noinst_HEADERS = gstspectrum.h
+
+Android.mk: Makefile.am $(BUILT_SOURCES)
+ androgenizer \
+ -:PROJECT libgstspectrum -:SHARED libgstspectrum \
+ -:TAGS eng debug \
+ -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
+ -:SOURCES $(libgstspectrum_la_SOURCES) \
+ $(nodist_libgstspectrum_la_SOURCES) \
+ -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstspectrum_la_CFLAGS) \
+ -:LDFLAGS $(libgstspectrum_la_LDFLAGS) \
+ $(libgstspectrum_la_LIBADD) \
+ -ldl \
+ -:PASSTHROUGH LOCAL_ARM_MODE:=arm \
+ LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \
+ > $@
diff --git a/gst/udp/Makefile.am b/gst/udp/Makefile.am
index 5b521eeb7..71a5971c5 100644
--- a/gst/udp/Makefile.am
+++ b/gst/udp/Makefile.am
@@ -32,3 +32,17 @@ EXTRA_DIST = README gstudp-marshal.list
CLEANFILES = $(BUILT_SOURCES)
+Android.mk: Makefile.am $(BUILT_SOURCES)
+ androgenizer \
+ -:PROJECT libgstudp -:SHARED libgstudp \
+ -:TAGS eng debug \
+ -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
+ -:SOURCES $(libgstudp_la_SOURCES) \
+ $(nodist_libgstudp_la_SOURCES) \
+ -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstudp_la_CFLAGS) \
+ -:LDFLAGS $(libgstudp_la_LDFLAGS) \
+ $(libgstudp_la_LIBADD) \
+ -ldl \
+ -:PASSTHROUGH LOCAL_ARM_MODE:=arm \
+ LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \
+ > $@
diff --git a/gst/videobox/Makefile.am b/gst/videobox/Makefile.am
index e34234f62..90dcd4b8f 100644
--- a/gst/videobox/Makefile.am
+++ b/gst/videobox/Makefile.am
@@ -21,3 +21,18 @@ libgstvideobox_la_LIBTOOLFLAGS = --tag=disable-static
noinst_HEADERS = gstvideobox.h
EXTRA_DIST += README
+
+Android.mk: Makefile.am $(BUILT_SOURCES)
+ androgenizer \
+ -:PROJECT libgstvideobox -:SHARED libgstvideobox \
+ -:TAGS eng debug \
+ -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
+ -:SOURCES $(libgstvideobox_la_SOURCES) \
+ $(nodist_libgstvideobox_la_SOURCES) \
+ -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstvideobox_la_CFLAGS) \
+ -:LDFLAGS $(libgstvideobox_la_LDFLAGS) \
+ $(libgstvideobox_la_LIBADD) \
+ -ldl \
+ -:PASSTHROUGH LOCAL_ARM_MODE:=arm \
+ LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \
+ > $@
diff --git a/gst/videobox/gstvideoboxorc-dist.c b/gst/videobox/gstvideoboxorc-dist.c
index f0e03f801..6e9cd105f 100644
--- a/gst/videobox/gstvideoboxorc-dist.c
+++ b/gst/videobox/gstvideoboxorc-dist.c
@@ -4,9 +4,6 @@
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
-#ifndef DISABLE_ORC
-#include <orc/orc.h>
-#endif
#include <glib.h>
#ifndef _ORC_INTEGER_TYPEDEFS_
@@ -32,6 +29,7 @@ typedef unsigned __int16 orc_uint16;
typedef unsigned __int32 orc_uint32;
typedef unsigned __int64 orc_uint64;
#define ORC_UINT64_C(x) (x##Ui64)
+#define inline __inline
#else
#include <limits.h>
typedef signed char orc_int8;
@@ -71,8 +69,20 @@ typedef union
orc_int16 x4[4];
} orc_union64;
#endif
+#ifndef ORC_RESTRICT
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+#define ORC_RESTRICT restrict
+#elif defined(__GNUC__) && __GNUC__ >= 4
+#define ORC_RESTRICT __restrict__
+#else
+#define ORC_RESTRICT
+#endif
+#endif
-void orc_splat_u32 (guint32 * d1, int p1, int n);
+#ifndef DISABLE_ORC
+#include <orc/orc.h>
+#endif
+void orc_splat_u32 (guint32 * ORC_RESTRICT d1, int p1, int n);
/* begin Orc C target preamble */
@@ -106,6 +116,7 @@ void orc_splat_u32 (guint32 * d1, int p1, int n);
#define ORC_ISNAN(x) ((((x)&0x7f800000) == 0x7f800000) && (((x)&0x007fffff) != 0))
#define ORC_DENORMAL_DOUBLE(x) ((x) & ((((x)&ORC_UINT64_C(0x7ff0000000000000)) == 0) ? ORC_UINT64_C(0xfff0000000000000) : ORC_UINT64_C(0xffffffffffffffff)))
#define ORC_ISNAN_DOUBLE(x) ((((x)&ORC_UINT64_C(0x7ff0000000000000)) == ORC_UINT64_C(0x7ff0000000000000)) && (((x)&ORC_UINT64_C(0x000fffffffffffff)) != 0))
+#ifndef ORC_RESTRICT
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
#define ORC_RESTRICT restrict
#elif defined(__GNUC__) && __GNUC__ >= 4
@@ -113,6 +124,7 @@ void orc_splat_u32 (guint32 * d1, int p1, int n);
#else
#define ORC_RESTRICT
#endif
+#endif
/* end Orc C target preamble */
@@ -120,7 +132,7 @@ void orc_splat_u32 (guint32 * d1, int p1, int n);
/* orc_splat_u32 */
#ifdef DISABLE_ORC
void
-orc_splat_u32 (guint32 * d1, int p1, int n)
+orc_splat_u32 (guint32 * ORC_RESTRICT d1, int p1, int n)
{
int i;
orc_union32 *ORC_RESTRICT ptr0;
@@ -166,7 +178,7 @@ _backup_orc_splat_u32 (OrcExecutor * ORC_RESTRICT ex)
}
void
-orc_splat_u32 (guint32 * d1, int p1, int n)
+orc_splat_u32 (guint32 * ORC_RESTRICT d1, int p1, int n)
{
OrcExecutor _ex, *ex = &_ex;
static int p_inited = 0;
@@ -176,7 +188,6 @@ orc_splat_u32 (guint32 * d1, int p1, int n)
if (!p_inited) {
orc_once_mutex_lock ();
if (!p_inited) {
- OrcCompileResult result;
p = orc_program_new ();
orc_program_set_name (p, "orc_splat_u32");
@@ -187,7 +198,7 @@ orc_splat_u32 (guint32 * d1, int p1, int n)
orc_program_append_2 (p, "copyl", 0, ORC_VAR_D1, ORC_VAR_P1, ORC_VAR_D1,
ORC_VAR_D1);
- result = orc_program_compile (p);
+ orc_program_compile (p);
}
p_inited = TRUE;
orc_once_mutex_unlock ();
diff --git a/gst/videobox/gstvideoboxorc-dist.h b/gst/videobox/gstvideoboxorc-dist.h
index e321c2934..1a711a54f 100644
--- a/gst/videobox/gstvideoboxorc-dist.h
+++ b/gst/videobox/gstvideoboxorc-dist.h
@@ -35,6 +35,7 @@ typedef unsigned __int16 orc_uint16;
typedef unsigned __int32 orc_uint32;
typedef unsigned __int64 orc_uint64;
#define ORC_UINT64_C(x) (x##Ui64)
+#define inline __inline
#else
#include <limits.h>
typedef signed char orc_int8;
@@ -57,7 +58,16 @@ typedef union { orc_int16 i; orc_int8 x2[2]; } orc_union16;
typedef union { orc_int32 i; float f; orc_int16 x2[2]; orc_int8 x4[4]; } orc_union32;
typedef union { orc_int64 i; double f; orc_int32 x2[2]; float x2f[2]; orc_int16 x4[4]; } orc_union64;
#endif
-void orc_splat_u32 (guint32 * d1, int p1, int n);
+#ifndef ORC_RESTRICT
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+#define ORC_RESTRICT restrict
+#elif defined(__GNUC__) && __GNUC__ >= 4
+#define ORC_RESTRICT __restrict__
+#else
+#define ORC_RESTRICT
+#endif
+#endif
+void orc_splat_u32 (guint32 * ORC_RESTRICT d1, int p1, int n);
#ifdef __cplusplus
}
diff --git a/gst/videocrop/Makefile.am b/gst/videocrop/Makefile.am
index e49ab3665..2b9838b65 100644
--- a/gst/videocrop/Makefile.am
+++ b/gst/videocrop/Makefile.am
@@ -11,3 +11,18 @@ libgstvideocrop_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
libgstvideocrop_la_LIBTOOLFLAGS = --tag=disable-static
noinst_HEADERS = gstvideocrop.h gstaspectratiocrop.h
+
+Android.mk: Makefile.am $(BUILT_SOURCES)
+ androgenizer \
+ -:PROJECT libgstvideocrop -:SHARED libgstvideocrop \
+ -:TAGS eng debug \
+ -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
+ -:SOURCES $(libgstvideocrop_la_SOURCES) \
+ $(nodist_libgstvideocrop_la_SOURCES) \
+ -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstvideocrop_la_CFLAGS) \
+ -:LDFLAGS $(libgstvideocrop_la_LDFLAGS) \
+ $(libgstvideocrop_la_LIBADD) \
+ -ldl \
+ -:PASSTHROUGH LOCAL_ARM_MODE:=arm \
+ LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \
+ > $@
diff --git a/gst/videofilter/Makefile.am b/gst/videofilter/Makefile.am
index c21b93ee6..4838c1724 100644
--- a/gst/videofilter/Makefile.am
+++ b/gst/videofilter/Makefile.am
@@ -22,3 +22,18 @@ libgstvideofilter_la_LIBTOOLFLAGS = --tag=disable-static
gstvideoexample.c: $(srcdir)/make_filter $(srcdir)/gstvideotemplate.c
$(srcdir)/make_filter Videoexample $(srcdir)/gstvideotemplate.c
+
+Android.mk: Makefile.am $(BUILT_SOURCES)
+ androgenizer \
+ -:PROJECT libgstvideofilter -:SHARED libgstvideofilter \
+ -:TAGS eng debug \
+ -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
+ -:SOURCES $(libgstvideofilter_la_SOURCES) \
+ $(nodist_libgstvideofilter_la_SOURCES) \
+ -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstvideofilter_la_CFLAGS) \
+ -:LDFLAGS $(libgstvideofilter_la_LDFLAGS) \
+ $(libgstvideofilter_la_LIBADD) \
+ -ldl \
+ -:PASSTHROUGH LOCAL_ARM_MODE:=arm \
+ LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \
+ > $@
diff --git a/gst/videofilter/gstvideobalance.c b/gst/videofilter/gstvideobalance.c
index 3be943c94..7fc56a672 100644
--- a/gst/videofilter/gstvideobalance.c
+++ b/gst/videofilter/gstvideobalance.c
@@ -233,8 +233,8 @@ gst_video_balance_planar_yuv (GstVideoBalance * videobalance, guint8 * data)
yptr = ydata + y * ystride;
for (x = 0; x < width; x++) {
- *ydata = tabley[*ydata];
- ydata++;
+ *yptr = tabley[*yptr];
+ yptr++;
}
}
@@ -294,8 +294,8 @@ gst_video_balance_packed_yuv (GstVideoBalance * videobalance, guint8 * data)
yptr = ydata + y * ystride;
for (x = 0; x < width; x++) {
- *ydata = tabley[*ydata];
- ydata += yoff;
+ *yptr = tabley[*yptr];
+ yptr += yoff;
}
}
@@ -670,7 +670,7 @@ gst_video_balance_colorbalance_set_value (GstColorBalance * balance,
{
GstVideoBalance *vb = GST_VIDEO_BALANCE (balance);
gdouble new_val;
- gboolean changed;
+ gboolean changed = FALSE;
g_return_if_fail (vb != NULL);
g_return_if_fail (GST_IS_VIDEO_BALANCE (vb));
@@ -697,12 +697,15 @@ gst_video_balance_colorbalance_set_value (GstColorBalance * balance,
vb->contrast = new_val;
}
- gst_video_balance_update_properties (vb);
+ if (changed)
+ gst_video_balance_update_properties (vb);
GST_OBJECT_UNLOCK (vb);
GST_BASE_TRANSFORM_UNLOCK (vb);
- gst_color_balance_value_changed (balance, channel,
- gst_color_balance_get_value (balance, channel));
+ if (changed) {
+ gst_color_balance_value_changed (balance, channel,
+ gst_color_balance_get_value (balance, channel));
+ }
}
static gint
diff --git a/gst/videofilter/gstvideoflip.c b/gst/videofilter/gstvideoflip.c
index f3612dfc5..3facdd1f5 100644
--- a/gst/videofilter/gstvideoflip.c
+++ b/gst/videofilter/gstvideoflip.c
@@ -588,8 +588,6 @@ gst_video_flip_y422 (GstVideoFlip * videoflip, guint8 * dest,
gint u_offset;
gint v_offset;
gint y_stride;
- gint u_stride;
- gint v_stride;
src_stride = gst_video_format_get_row_stride (format, 0, sw);
dest_stride = gst_video_format_get_row_stride (format, 0, dw);
@@ -598,8 +596,6 @@ gst_video_flip_y422 (GstVideoFlip * videoflip, guint8 * dest,
u_offset = gst_video_format_get_component_offset (format, 1, sw, sh);
v_offset = gst_video_format_get_component_offset (format, 2, sw, sh);
y_stride = gst_video_format_get_pixel_stride (format, 0);
- u_stride = gst_video_format_get_pixel_stride (format, 1);
- v_stride = gst_video_format_get_pixel_stride (format, 2);
bpp = y_stride;
switch (videoflip->method) {
diff --git a/gst/videomixer/Makefile.am b/gst/videomixer/Makefile.am
index 778af4dbd..4a9ac7b09 100644
--- a/gst/videomixer/Makefile.am
+++ b/gst/videomixer/Makefile.am
@@ -28,3 +28,18 @@ noinst_HEADERS = \
videomixer2.h \
videomixer2pad.h \
gstcollectpads2.h
+
+Android.mk: Makefile.am $(BUILT_SOURCES)
+ androgenizer \
+ -:PROJECT libgstvideomixer -:SHARED libgstvideomixer \
+ -:TAGS eng debug \
+ -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
+ -:SOURCES $(libgstvideomixer_la_SOURCES) \
+ $(nodist_libgstvideomixer_la_SOURCES) \
+ -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstvideomixer_la_CFLAGS) \
+ -:LDFLAGS $(libgstvideomixer_la_LDFLAGS) \
+ $(libgstvideomixer_la_LIBADD) \
+ -ldl \
+ -:PASSTHROUGH LOCAL_ARM_MODE:=arm \
+ LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \
+ > $@
diff --git a/gst/videomixer/blend.c b/gst/videomixer/blend.c
index e2d736ff4..aeeeef157 100644
--- a/gst/videomixer/blend.c
+++ b/gst/videomixer/blend.c
@@ -221,8 +221,8 @@ blend_##format_name (const guint8 * src, gint xpos, gint ypos, \
gint xoffset = 0; \
gint yoffset = 0; \
gint src_comp_rowstride, dest_comp_rowstride; \
- gint src_comp_height, dest_comp_height; \
- gint src_comp_width, dest_comp_width; \
+ gint src_comp_height; \
+ gint src_comp_width; \
gint comp_ypos, comp_xpos; \
gint comp_yoffset, comp_xoffset; \
\
@@ -262,9 +262,7 @@ blend_##format_name (const guint8 * src, gint xpos, gint ypos, \
src_comp_rowstride = gst_video_format_get_row_stride (format_enum, 0, src_width); \
dest_comp_rowstride = gst_video_format_get_row_stride (format_enum, 0, dest_width); \
src_comp_height = gst_video_format_get_component_height (format_enum, 0, b_src_height); \
- dest_comp_height = gst_video_format_get_component_height (format_enum, 0, dest_height); \
src_comp_width = gst_video_format_get_component_width (format_enum, 0, b_src_width); \
- dest_comp_width = gst_video_format_get_component_width (format_enum, 0, dest_width); \
comp_xpos = (xpos == 0) ? 0 : gst_video_format_get_component_width (format_enum, 0, xpos); \
comp_ypos = (ypos == 0) ? 0 : gst_video_format_get_component_height (format_enum, 0, ypos); \
comp_xoffset = (xoffset == 0) ? 0 : gst_video_format_get_component_width (format_enum, 0, xoffset); \
@@ -280,9 +278,7 @@ blend_##format_name (const guint8 * src, gint xpos, gint ypos, \
src_comp_rowstride = gst_video_format_get_row_stride (format_enum, 1, src_width); \
dest_comp_rowstride = gst_video_format_get_row_stride (format_enum, 1, dest_width); \
src_comp_height = gst_video_format_get_component_height (format_enum, 1, b_src_height); \
- dest_comp_height = gst_video_format_get_component_height (format_enum, 1, dest_height); \
src_comp_width = gst_video_format_get_component_width (format_enum, 1, b_src_width); \
- dest_comp_width = gst_video_format_get_component_width (format_enum, 1, dest_width); \
comp_xpos = (xpos == 0) ? 0 : gst_video_format_get_component_width (format_enum, 1, xpos); \
comp_ypos = (ypos == 0) ? 0 : gst_video_format_get_component_height (format_enum, 1, ypos); \
comp_xoffset = (xoffset == 0) ? 0 : gst_video_format_get_component_width (format_enum, 1, xoffset); \
@@ -298,9 +294,7 @@ blend_##format_name (const guint8 * src, gint xpos, gint ypos, \
src_comp_rowstride = gst_video_format_get_row_stride (format_enum, 2, src_width); \
dest_comp_rowstride = gst_video_format_get_row_stride (format_enum, 2, dest_width); \
src_comp_height = gst_video_format_get_component_height (format_enum, 2, b_src_height); \
- dest_comp_height = gst_video_format_get_component_height (format_enum, 2, dest_height); \
src_comp_width = gst_video_format_get_component_width (format_enum, 2, b_src_width); \
- dest_comp_width = gst_video_format_get_component_width (format_enum, 2, dest_width); \
comp_xpos = (xpos == 0) ? 0 : gst_video_format_get_component_width (format_enum, 2, xpos); \
comp_ypos = (ypos == 0) ? 0 : gst_video_format_get_component_height (format_enum, 2, ypos); \
comp_xoffset = (xoffset == 0) ? 0 : gst_video_format_get_component_width (format_enum, 2, xoffset); \
diff --git a/gst/videomixer/blendorc-dist.c b/gst/videomixer/blendorc-dist.c
index 8ead5bb3e..21b6ae1ab 100644
--- a/gst/videomixer/blendorc-dist.c
+++ b/gst/videomixer/blendorc-dist.c
@@ -4,9 +4,6 @@
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
-#ifndef DISABLE_ORC
-#include <orc/orc.h>
-#endif
#include <glib.h>
#ifndef _ORC_INTEGER_TYPEDEFS_
@@ -72,19 +69,32 @@ typedef union
orc_int16 x4[4];
} orc_union64;
#endif
+#ifndef ORC_RESTRICT
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+#define ORC_RESTRICT restrict
+#elif defined(__GNUC__) && __GNUC__ >= 4
+#define ORC_RESTRICT __restrict__
+#else
+#define ORC_RESTRICT
+#endif
+#endif
-void orc_splat_u32 (guint32 * d1, int p1, int n);
-void orc_memcpy_u32 (guint32 * d1, const guint32 * s1, int n);
-void orc_blend_u8 (guint8 * d1, int d1_stride, const guint8 * s1, int s1_stride,
- int p1, int n, int m);
-void orc_blend_argb (guint8 * d1, int d1_stride, const guint8 * s1,
- int s1_stride, int p1, int n, int m);
-void orc_blend_bgra (guint8 * d1, int d1_stride, const guint8 * s1,
- int s1_stride, int p1, int n, int m);
-void orc_overlay_argb (guint8 * d1, int d1_stride, const guint8 * s1,
- int s1_stride, int p1, int n, int m);
-void orc_overlay_bgra (guint8 * d1, int d1_stride, const guint8 * s1,
- int s1_stride, int p1, int n, int m);
+#ifndef DISABLE_ORC
+#include <orc/orc.h>
+#endif
+void orc_splat_u32 (guint32 * ORC_RESTRICT d1, int p1, int n);
+void orc_memcpy_u32 (guint32 * ORC_RESTRICT d1, const guint32 * ORC_RESTRICT s1,
+ int n);
+void orc_blend_u8 (guint8 * ORC_RESTRICT d1, int d1_stride,
+ const guint8 * ORC_RESTRICT s1, int s1_stride, int p1, int n, int m);
+void orc_blend_argb (guint8 * ORC_RESTRICT d1, int d1_stride,
+ const guint8 * ORC_RESTRICT s1, int s1_stride, int p1, int n, int m);
+void orc_blend_bgra (guint8 * ORC_RESTRICT d1, int d1_stride,
+ const guint8 * ORC_RESTRICT s1, int s1_stride, int p1, int n, int m);
+void orc_overlay_argb (guint8 * ORC_RESTRICT d1, int d1_stride,
+ const guint8 * ORC_RESTRICT s1, int s1_stride, int p1, int n, int m);
+void orc_overlay_bgra (guint8 * ORC_RESTRICT d1, int d1_stride,
+ const guint8 * ORC_RESTRICT s1, int s1_stride, int p1, int n, int m);
/* begin Orc C target preamble */
@@ -118,6 +128,7 @@ void orc_overlay_bgra (guint8 * d1, int d1_stride, const guint8 * s1,
#define ORC_ISNAN(x) ((((x)&0x7f800000) == 0x7f800000) && (((x)&0x007fffff) != 0))
#define ORC_DENORMAL_DOUBLE(x) ((x) & ((((x)&ORC_UINT64_C(0x7ff0000000000000)) == 0) ? ORC_UINT64_C(0xfff0000000000000) : ORC_UINT64_C(0xffffffffffffffff)))
#define ORC_ISNAN_DOUBLE(x) ((((x)&ORC_UINT64_C(0x7ff0000000000000)) == ORC_UINT64_C(0x7ff0000000000000)) && (((x)&ORC_UINT64_C(0x000fffffffffffff)) != 0))
+#ifndef ORC_RESTRICT
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
#define ORC_RESTRICT restrict
#elif defined(__GNUC__) && __GNUC__ >= 4
@@ -125,6 +136,7 @@ void orc_overlay_bgra (guint8 * d1, int d1_stride, const guint8 * s1,
#else
#define ORC_RESTRICT
#endif
+#endif
/* end Orc C target preamble */
@@ -132,7 +144,7 @@ void orc_overlay_bgra (guint8 * d1, int d1_stride, const guint8 * s1,
/* orc_splat_u32 */
#ifdef DISABLE_ORC
void
-orc_splat_u32 (guint32 * d1, int p1, int n)
+orc_splat_u32 (guint32 * ORC_RESTRICT d1, int p1, int n)
{
int i;
orc_union32 *ORC_RESTRICT ptr0;
@@ -178,7 +190,7 @@ _backup_orc_splat_u32 (OrcExecutor * ORC_RESTRICT ex)
}
void
-orc_splat_u32 (guint32 * d1, int p1, int n)
+orc_splat_u32 (guint32 * ORC_RESTRICT d1, int p1, int n)
{
OrcExecutor _ex, *ex = &_ex;
static int p_inited = 0;
@@ -188,7 +200,6 @@ orc_splat_u32 (guint32 * d1, int p1, int n)
if (!p_inited) {
orc_once_mutex_lock ();
if (!p_inited) {
- OrcCompileResult result;
p = orc_program_new ();
orc_program_set_name (p, "orc_splat_u32");
@@ -199,7 +210,7 @@ orc_splat_u32 (guint32 * d1, int p1, int n)
orc_program_append_2 (p, "copyl", 0, ORC_VAR_D1, ORC_VAR_P1, ORC_VAR_D1,
ORC_VAR_D1);
- result = orc_program_compile (p);
+ orc_program_compile (p);
}
p_inited = TRUE;
orc_once_mutex_unlock ();
@@ -219,7 +230,8 @@ orc_splat_u32 (guint32 * d1, int p1, int n)
/* orc_memcpy_u32 */
#ifdef DISABLE_ORC
void
-orc_memcpy_u32 (guint32 * d1, const guint32 * s1, int n)
+orc_memcpy_u32 (guint32 * ORC_RESTRICT d1, const guint32 * ORC_RESTRICT s1,
+ int n)
{
int i;
orc_union32 *ORC_RESTRICT ptr0;
@@ -269,7 +281,8 @@ _backup_orc_memcpy_u32 (OrcExecutor * ORC_RESTRICT ex)
}
void
-orc_memcpy_u32 (guint32 * d1, const guint32 * s1, int n)
+orc_memcpy_u32 (guint32 * ORC_RESTRICT d1, const guint32 * ORC_RESTRICT s1,
+ int n)
{
OrcExecutor _ex, *ex = &_ex;
static int p_inited = 0;
@@ -279,7 +292,6 @@ orc_memcpy_u32 (guint32 * d1, const guint32 * s1, int n)
if (!p_inited) {
orc_once_mutex_lock ();
if (!p_inited) {
- OrcCompileResult result;
p = orc_program_new ();
orc_program_set_name (p, "orc_memcpy_u32");
@@ -290,7 +302,7 @@ orc_memcpy_u32 (guint32 * d1, const guint32 * s1, int n)
orc_program_append_2 (p, "copyl", 0, ORC_VAR_D1, ORC_VAR_S1, ORC_VAR_D1,
ORC_VAR_D1);
- result = orc_program_compile (p);
+ orc_program_compile (p);
}
p_inited = TRUE;
orc_once_mutex_unlock ();
@@ -310,8 +322,8 @@ orc_memcpy_u32 (guint32 * d1, const guint32 * s1, int n)
/* orc_blend_u8 */
#ifdef DISABLE_ORC
void
-orc_blend_u8 (guint8 * d1, int d1_stride, const guint8 * s1, int s1_stride,
- int p1, int n, int m)
+orc_blend_u8 (guint8 * ORC_RESTRICT d1, int d1_stride,
+ const guint8 * ORC_RESTRICT s1, int s1_stride, int p1, int n, int m)
{
int i;
int j;
@@ -422,8 +434,8 @@ _backup_orc_blend_u8 (OrcExecutor * ORC_RESTRICT ex)
}
void
-orc_blend_u8 (guint8 * d1, int d1_stride, const guint8 * s1, int s1_stride,
- int p1, int n, int m)
+orc_blend_u8 (guint8 * ORC_RESTRICT d1, int d1_stride,
+ const guint8 * ORC_RESTRICT s1, int s1_stride, int p1, int n, int m)
{
OrcExecutor _ex, *ex = &_ex;
static int p_inited = 0;
@@ -433,7 +445,6 @@ orc_blend_u8 (guint8 * d1, int d1_stride, const guint8 * s1, int s1_stride,
if (!p_inited) {
orc_once_mutex_lock ();
if (!p_inited) {
- OrcCompileResult result;
p = orc_program_new ();
orc_program_set_2d (p);
@@ -463,7 +474,7 @@ orc_blend_u8 (guint8 * d1, int d1_stride, const guint8 * s1, int s1_stride,
orc_program_append_2 (p, "convsuswb", 0, ORC_VAR_D1, ORC_VAR_T2,
ORC_VAR_D1, ORC_VAR_D1);
- result = orc_program_compile (p);
+ orc_program_compile (p);
}
p_inited = TRUE;
orc_once_mutex_unlock ();
@@ -487,8 +498,8 @@ orc_blend_u8 (guint8 * d1, int d1_stride, const guint8 * s1, int s1_stride,
/* orc_blend_argb */
#ifdef DISABLE_ORC
void
-orc_blend_argb (guint8 * d1, int d1_stride, const guint8 * s1, int s1_stride,
- int p1, int n, int m)
+orc_blend_argb (guint8 * ORC_RESTRICT d1, int d1_stride,
+ const guint8 * ORC_RESTRICT s1, int s1_stride, int p1, int n, int m)
{
int i;
int j;
@@ -727,8 +738,8 @@ _backup_orc_blend_argb (OrcExecutor * ORC_RESTRICT ex)
}
void
-orc_blend_argb (guint8 * d1, int d1_stride, const guint8 * s1, int s1_stride,
- int p1, int n, int m)
+orc_blend_argb (guint8 * ORC_RESTRICT d1, int d1_stride,
+ const guint8 * ORC_RESTRICT s1, int s1_stride, int p1, int n, int m)
{
OrcExecutor _ex, *ex = &_ex;
static int p_inited = 0;
@@ -738,7 +749,6 @@ orc_blend_argb (guint8 * d1, int d1_stride, const guint8 * s1, int s1_stride,
if (!p_inited) {
orc_once_mutex_lock ();
if (!p_inited) {
- OrcCompileResult result;
p = orc_program_new ();
orc_program_set_2d (p);
@@ -792,7 +802,7 @@ orc_blend_argb (guint8 * d1, int d1_stride, const guint8 * s1, int s1_stride,
orc_program_append_2 (p, "storel", 0, ORC_VAR_D1, ORC_VAR_T1, ORC_VAR_D1,
ORC_VAR_D1);
- result = orc_program_compile (p);
+ orc_program_compile (p);
}
p_inited = TRUE;
orc_once_mutex_unlock ();
@@ -816,8 +826,8 @@ orc_blend_argb (guint8 * d1, int d1_stride, const guint8 * s1, int s1_stride,
/* orc_blend_bgra */
#ifdef DISABLE_ORC
void
-orc_blend_bgra (guint8 * d1, int d1_stride, const guint8 * s1, int s1_stride,
- int p1, int n, int m)
+orc_blend_bgra (guint8 * ORC_RESTRICT d1, int d1_stride,
+ const guint8 * ORC_RESTRICT s1, int s1_stride, int p1, int n, int m)
{
int i;
int j;
@@ -1062,8 +1072,8 @@ _backup_orc_blend_bgra (OrcExecutor * ORC_RESTRICT ex)
}
void
-orc_blend_bgra (guint8 * d1, int d1_stride, const guint8 * s1, int s1_stride,
- int p1, int n, int m)
+orc_blend_bgra (guint8 * ORC_RESTRICT d1, int d1_stride,
+ const guint8 * ORC_RESTRICT s1, int s1_stride, int p1, int n, int m)
{
OrcExecutor _ex, *ex = &_ex;
static int p_inited = 0;
@@ -1073,7 +1083,6 @@ orc_blend_bgra (guint8 * d1, int d1_stride, const guint8 * s1, int s1_stride,
if (!p_inited) {
orc_once_mutex_lock ();
if (!p_inited) {
- OrcCompileResult result;
p = orc_program_new ();
orc_program_set_2d (p);
@@ -1131,7 +1140,7 @@ orc_blend_bgra (guint8 * d1, int d1_stride, const guint8 * s1, int s1_stride,
orc_program_append_2 (p, "storel", 0, ORC_VAR_D1, ORC_VAR_T1, ORC_VAR_D1,
ORC_VAR_D1);
- result = orc_program_compile (p);
+ orc_program_compile (p);
}
p_inited = TRUE;
orc_once_mutex_unlock ();
@@ -1155,8 +1164,8 @@ orc_blend_bgra (guint8 * d1, int d1_stride, const guint8 * s1, int s1_stride,
/* orc_overlay_argb */
#ifdef DISABLE_ORC
void
-orc_overlay_argb (guint8 * d1, int d1_stride, const guint8 * s1, int s1_stride,
- int p1, int n, int m)
+orc_overlay_argb (guint8 * ORC_RESTRICT d1, int d1_stride,
+ const guint8 * ORC_RESTRICT s1, int s1_stride, int p1, int n, int m)
{
int i;
int j;
@@ -1180,8 +1189,8 @@ orc_overlay_argb (guint8 * d1, int d1_stride, const guint8 * s1, int s1_stride,
orc_union32 var56;
orc_union16 var57;
orc_int8 var58;
- orc_union16 var59;
- orc_union32 var60;
+ orc_union32 var59;
+ orc_union64 var60;
orc_union64 var61;
orc_union64 var62;
orc_union64 var63;
@@ -1189,12 +1198,11 @@ orc_overlay_argb (guint8 * d1, int d1_stride, const guint8 * s1, int s1_stride,
orc_union64 var65;
orc_union64 var66;
orc_union64 var67;
- orc_union64 var68;
+ orc_union32 var68;
orc_union32 var69;
orc_union32 var70;
orc_union32 var71;
orc_union32 var72;
- orc_union32 var73;
for (j = 0; j < m; j++) {
ptr0 = ORC_PTR_OFFSET (d1, d1_stride * j);
@@ -1207,9 +1215,9 @@ orc_overlay_argb (guint8 * d1, int d1_stride, const guint8 * s1, int s1_stride,
var41.x4[3] = p1;
/* 10: loadpl */
var53.i = (int) 0xffffffff; /* -1 or 2.122e-314f */
- /* 27: loadpl */
+ /* 26: loadpl */
var42.i = (int) 0xffffff00; /* -256 or 2.122e-314f */
- /* 30: loadpl */
+ /* 29: loadpl */
var43.i = (int) 0x000000ff; /* 255 or 1.25987e-321f */
for (i = 0; i < n; i++) {
@@ -1264,90 +1272,88 @@ orc_overlay_argb (guint8 * d1, int d1_stride, const guint8 * s1, int s1_stride,
var57.i = var56.i;
/* 15: convwb */
var58 = var57.i;
- /* 16: convubw */
- var59.i = (orc_uint8) var58;
- /* 17: splatbl */
- var60.i =
+ /* 16: splatbl */
+ var59.i =
((var58 & 0xff) << 24) | ((var58 & 0xff) << 16) | ((var58 & 0xff) <<
8) | (var58 & 0xff);
- /* 18: convubw */
- var61.x4[0] = (orc_uint8) var60.x4[0];
- var61.x4[1] = (orc_uint8) var60.x4[1];
- var61.x4[2] = (orc_uint8) var60.x4[2];
- var61.x4[3] = (orc_uint8) var60.x4[3];
- /* 19: mullw */
- var62.x4[0] = (var61.x4[0] * var55.x4[0]) & 0xffff;
- var62.x4[1] = (var61.x4[1] * var55.x4[1]) & 0xffff;
- var62.x4[2] = (var61.x4[2] * var55.x4[2]) & 0xffff;
- var62.x4[3] = (var61.x4[3] * var55.x4[3]) & 0xffff;
- /* 20: div255w */
- var63.x4[0] =
- ((orc_uint16) (((orc_uint16) (var62.x4[0] + 128)) +
- (((orc_uint16) (var62.x4[0] + 128)) >> 8))) >> 8;
- var63.x4[1] =
- ((orc_uint16) (((orc_uint16) (var62.x4[1] + 128)) +
- (((orc_uint16) (var62.x4[1] + 128)) >> 8))) >> 8;
- var63.x4[2] =
- ((orc_uint16) (((orc_uint16) (var62.x4[2] + 128)) +
- (((orc_uint16) (var62.x4[2] + 128)) >> 8))) >> 8;
- var63.x4[3] =
- ((orc_uint16) (((orc_uint16) (var62.x4[3] + 128)) +
- (((orc_uint16) (var62.x4[3] + 128)) >> 8))) >> 8;
- /* 21: convubw */
- var64.x4[0] = (orc_uint8) var56.x4[0];
- var64.x4[1] = (orc_uint8) var56.x4[1];
- var64.x4[2] = (orc_uint8) var56.x4[2];
- var64.x4[3] = (orc_uint8) var56.x4[3];
- /* 22: mullw */
- var65.x4[0] = (var64.x4[0] * var63.x4[0]) & 0xffff;
- var65.x4[1] = (var64.x4[1] * var63.x4[1]) & 0xffff;
- var65.x4[2] = (var64.x4[2] * var63.x4[2]) & 0xffff;
- var65.x4[3] = (var64.x4[3] * var63.x4[3]) & 0xffff;
+ /* 17: convubw */
+ var60.x4[0] = (orc_uint8) var59.x4[0];
+ var60.x4[1] = (orc_uint8) var59.x4[1];
+ var60.x4[2] = (orc_uint8) var59.x4[2];
+ var60.x4[3] = (orc_uint8) var59.x4[3];
+ /* 18: mullw */
+ var61.x4[0] = (var60.x4[0] * var55.x4[0]) & 0xffff;
+ var61.x4[1] = (var60.x4[1] * var55.x4[1]) & 0xffff;
+ var61.x4[2] = (var60.x4[2] * var55.x4[2]) & 0xffff;
+ var61.x4[3] = (var60.x4[3] * var55.x4[3]) & 0xffff;
+ /* 19: div255w */
+ var62.x4[0] =
+ ((orc_uint16) (((orc_uint16) (var61.x4[0] + 128)) +
+ (((orc_uint16) (var61.x4[0] + 128)) >> 8))) >> 8;
+ var62.x4[1] =
+ ((orc_uint16) (((orc_uint16) (var61.x4[1] + 128)) +
+ (((orc_uint16) (var61.x4[1] + 128)) >> 8))) >> 8;
+ var62.x4[2] =
+ ((orc_uint16) (((orc_uint16) (var61.x4[2] + 128)) +
+ (((orc_uint16) (var61.x4[2] + 128)) >> 8))) >> 8;
+ var62.x4[3] =
+ ((orc_uint16) (((orc_uint16) (var61.x4[3] + 128)) +
+ (((orc_uint16) (var61.x4[3] + 128)) >> 8))) >> 8;
+ /* 20: convubw */
+ var63.x4[0] = (orc_uint8) var56.x4[0];
+ var63.x4[1] = (orc_uint8) var56.x4[1];
+ var63.x4[2] = (orc_uint8) var56.x4[2];
+ var63.x4[3] = (orc_uint8) var56.x4[3];
+ /* 21: mullw */
+ var64.x4[0] = (var63.x4[0] * var62.x4[0]) & 0xffff;
+ var64.x4[1] = (var63.x4[1] * var62.x4[1]) & 0xffff;
+ var64.x4[2] = (var63.x4[2] * var62.x4[2]) & 0xffff;
+ var64.x4[3] = (var63.x4[3] * var62.x4[3]) & 0xffff;
+ /* 22: addw */
+ var65.x4[0] = var64.x4[0] + var52.x4[0];
+ var65.x4[1] = var64.x4[1] + var52.x4[1];
+ var65.x4[2] = var64.x4[2] + var52.x4[2];
+ var65.x4[3] = var64.x4[3] + var52.x4[3];
/* 23: addw */
- var66.x4[0] = var65.x4[0] + var52.x4[0];
- var66.x4[1] = var65.x4[1] + var52.x4[1];
- var66.x4[2] = var65.x4[2] + var52.x4[2];
- var66.x4[3] = var65.x4[3] + var52.x4[3];
- /* 24: addw */
- var67.x4[0] = var63.x4[0] + var50.x4[0];
- var67.x4[1] = var63.x4[1] + var50.x4[1];
- var67.x4[2] = var63.x4[2] + var50.x4[2];
- var67.x4[3] = var63.x4[3] + var50.x4[3];
- /* 25: divluw */
- var68.x4[0] =
- ((var67.x4[0] & 0xff) ==
- 0) ? 255 : ORC_CLAMP_UB (((orc_uint16) var66.x4[0]) /
- ((orc_uint16) var67.x4[0] & 0xff));
- var68.x4[1] =
- ((var67.x4[1] & 0xff) ==
- 0) ? 255 : ORC_CLAMP_UB (((orc_uint16) var66.x4[1]) /
- ((orc_uint16) var67.x4[1] & 0xff));
- var68.x4[2] =
- ((var67.x4[2] & 0xff) ==
- 0) ? 255 : ORC_CLAMP_UB (((orc_uint16) var66.x4[2]) /
- ((orc_uint16) var67.x4[2] & 0xff));
- var68.x4[3] =
- ((var67.x4[3] & 0xff) ==
- 0) ? 255 : ORC_CLAMP_UB (((orc_uint16) var66.x4[3]) /
- ((orc_uint16) var67.x4[3] & 0xff));
- /* 26: convwb */
- var69.x4[0] = var68.x4[0];
- var69.x4[1] = var68.x4[1];
- var69.x4[2] = var68.x4[2];
- var69.x4[3] = var68.x4[3];
- /* 28: andl */
- var70.i = var69.i & var42.i;
- /* 29: convwb */
- var71.x4[0] = var67.x4[0];
- var71.x4[1] = var67.x4[1];
- var71.x4[2] = var67.x4[2];
- var71.x4[3] = var67.x4[3];
- /* 31: andl */
- var72.i = var71.i & var43.i;
- /* 32: orl */
- var73.i = var70.i | var72.i;
- /* 33: storel */
- ptr0[i] = var73;
+ var66.x4[0] = var62.x4[0] + var50.x4[0];
+ var66.x4[1] = var62.x4[1] + var50.x4[1];
+ var66.x4[2] = var62.x4[2] + var50.x4[2];
+ var66.x4[3] = var62.x4[3] + var50.x4[3];
+ /* 24: divluw */
+ var67.x4[0] =
+ ((var66.x4[0] & 0xff) ==
+ 0) ? 255 : ORC_CLAMP_UB (((orc_uint16) var65.x4[0]) /
+ ((orc_uint16) var66.x4[0] & 0xff));
+ var67.x4[1] =
+ ((var66.x4[1] & 0xff) ==
+ 0) ? 255 : ORC_CLAMP_UB (((orc_uint16) var65.x4[1]) /
+ ((orc_uint16) var66.x4[1] & 0xff));
+ var67.x4[2] =
+ ((var66.x4[2] & 0xff) ==
+ 0) ? 255 : ORC_CLAMP_UB (((orc_uint16) var65.x4[2]) /
+ ((orc_uint16) var66.x4[2] & 0xff));
+ var67.x4[3] =
+ ((var66.x4[3] & 0xff) ==
+ 0) ? 255 : ORC_CLAMP_UB (((orc_uint16) var65.x4[3]) /
+ ((orc_uint16) var66.x4[3] & 0xff));
+ /* 25: convwb */
+ var68.x4[0] = var67.x4[0];
+ var68.x4[1] = var67.x4[1];
+ var68.x4[2] = var67.x4[2];
+ var68.x4[3] = var67.x4[3];
+ /* 27: andl */
+ var69.i = var68.i & var42.i;
+ /* 28: convwb */
+ var70.x4[0] = var66.x4[0];
+ var70.x4[1] = var66.x4[1];
+ var70.x4[2] = var66.x4[2];
+ var70.x4[3] = var66.x4[3];
+ /* 30: andl */
+ var71.i = var70.i & var43.i;
+ /* 31: orl */
+ var72.i = var69.i | var71.i;
+ /* 32: storel */
+ ptr0[i] = var72;
}
}
@@ -1381,8 +1387,8 @@ _backup_orc_overlay_argb (OrcExecutor * ORC_RESTRICT ex)
orc_union32 var56;
orc_union16 var57;
orc_int8 var58;
- orc_union16 var59;
- orc_union32 var60;
+ orc_union32 var59;
+ orc_union64 var60;
orc_union64 var61;
orc_union64 var62;
orc_union64 var63;
@@ -1390,12 +1396,11 @@ _backup_orc_overlay_argb (OrcExecutor * ORC_RESTRICT ex)
orc_union64 var65;
orc_union64 var66;
orc_union64 var67;
- orc_union64 var68;
+ orc_union32 var68;
orc_union32 var69;
orc_union32 var70;
orc_union32 var71;
orc_union32 var72;
- orc_union32 var73;
for (j = 0; j < m; j++) {
ptr0 = ORC_PTR_OFFSET (ex->arrays[0], ex->params[0] * j);
@@ -1408,9 +1413,9 @@ _backup_orc_overlay_argb (OrcExecutor * ORC_RESTRICT ex)
var41.x4[3] = ex->params[24];
/* 10: loadpl */
var53.i = (int) 0xffffffff; /* -1 or 2.122e-314f */
- /* 27: loadpl */
+ /* 26: loadpl */
var42.i = (int) 0xffffff00; /* -256 or 2.122e-314f */
- /* 30: loadpl */
+ /* 29: loadpl */
var43.i = (int) 0x000000ff; /* 255 or 1.25987e-321f */
for (i = 0; i < n; i++) {
@@ -1465,98 +1470,96 @@ _backup_orc_overlay_argb (OrcExecutor * ORC_RESTRICT ex)
var57.i = var56.i;
/* 15: convwb */
var58 = var57.i;
- /* 16: convubw */
- var59.i = (orc_uint8) var58;
- /* 17: splatbl */
- var60.i =
+ /* 16: splatbl */
+ var59.i =
((var58 & 0xff) << 24) | ((var58 & 0xff) << 16) | ((var58 & 0xff) <<
8) | (var58 & 0xff);
- /* 18: convubw */
- var61.x4[0] = (orc_uint8) var60.x4[0];
- var61.x4[1] = (orc_uint8) var60.x4[1];
- var61.x4[2] = (orc_uint8) var60.x4[2];
- var61.x4[3] = (orc_uint8) var60.x4[3];
- /* 19: mullw */
- var62.x4[0] = (var61.x4[0] * var55.x4[0]) & 0xffff;
- var62.x4[1] = (var61.x4[1] * var55.x4[1]) & 0xffff;
- var62.x4[2] = (var61.x4[2] * var55.x4[2]) & 0xffff;
- var62.x4[3] = (var61.x4[3] * var55.x4[3]) & 0xffff;
- /* 20: div255w */
- var63.x4[0] =
- ((orc_uint16) (((orc_uint16) (var62.x4[0] + 128)) +
- (((orc_uint16) (var62.x4[0] + 128)) >> 8))) >> 8;
- var63.x4[1] =
- ((orc_uint16) (((orc_uint16) (var62.x4[1] + 128)) +
- (((orc_uint16) (var62.x4[1] + 128)) >> 8))) >> 8;
- var63.x4[2] =
- ((orc_uint16) (((orc_uint16) (var62.x4[2] + 128)) +
- (((orc_uint16) (var62.x4[2] + 128)) >> 8))) >> 8;
- var63.x4[3] =
- ((orc_uint16) (((orc_uint16) (var62.x4[3] + 128)) +
- (((orc_uint16) (var62.x4[3] + 128)) >> 8))) >> 8;
- /* 21: convubw */
- var64.x4[0] = (orc_uint8) var56.x4[0];
- var64.x4[1] = (orc_uint8) var56.x4[1];
- var64.x4[2] = (orc_uint8) var56.x4[2];
- var64.x4[3] = (orc_uint8) var56.x4[3];
- /* 22: mullw */
- var65.x4[0] = (var64.x4[0] * var63.x4[0]) & 0xffff;
- var65.x4[1] = (var64.x4[1] * var63.x4[1]) & 0xffff;
- var65.x4[2] = (var64.x4[2] * var63.x4[2]) & 0xffff;
- var65.x4[3] = (var64.x4[3] * var63.x4[3]) & 0xffff;
+ /* 17: convubw */
+ var60.x4[0] = (orc_uint8) var59.x4[0];
+ var60.x4[1] = (orc_uint8) var59.x4[1];
+ var60.x4[2] = (orc_uint8) var59.x4[2];
+ var60.x4[3] = (orc_uint8) var59.x4[3];
+ /* 18: mullw */
+ var61.x4[0] = (var60.x4[0] * var55.x4[0]) & 0xffff;
+ var61.x4[1] = (var60.x4[1] * var55.x4[1]) & 0xffff;
+ var61.x4[2] = (var60.x4[2] * var55.x4[2]) & 0xffff;
+ var61.x4[3] = (var60.x4[3] * var55.x4[3]) & 0xffff;
+ /* 19: div255w */
+ var62.x4[0] =
+ ((orc_uint16) (((orc_uint16) (var61.x4[0] + 128)) +
+ (((orc_uint16) (var61.x4[0] + 128)) >> 8))) >> 8;
+ var62.x4[1] =
+ ((orc_uint16) (((orc_uint16) (var61.x4[1] + 128)) +
+ (((orc_uint16) (var61.x4[1] + 128)) >> 8))) >> 8;
+ var62.x4[2] =
+ ((orc_uint16) (((orc_uint16) (var61.x4[2] + 128)) +
+ (((orc_uint16) (var61.x4[2] + 128)) >> 8))) >> 8;
+ var62.x4[3] =
+ ((orc_uint16) (((orc_uint16) (var61.x4[3] + 128)) +
+ (((orc_uint16) (var61.x4[3] + 128)) >> 8))) >> 8;
+ /* 20: convubw */
+ var63.x4[0] = (orc_uint8) var56.x4[0];
+ var63.x4[1] = (orc_uint8) var56.x4[1];
+ var63.x4[2] = (orc_uint8) var56.x4[2];
+ var63.x4[3] = (orc_uint8) var56.x4[3];
+ /* 21: mullw */
+ var64.x4[0] = (var63.x4[0] * var62.x4[0]) & 0xffff;
+ var64.x4[1] = (var63.x4[1] * var62.x4[1]) & 0xffff;
+ var64.x4[2] = (var63.x4[2] * var62.x4[2]) & 0xffff;
+ var64.x4[3] = (var63.x4[3] * var62.x4[3]) & 0xffff;
+ /* 22: addw */
+ var65.x4[0] = var64.x4[0] + var52.x4[0];
+ var65.x4[1] = var64.x4[1] + var52.x4[1];
+ var65.x4[2] = var64.x4[2] + var52.x4[2];
+ var65.x4[3] = var64.x4[3] + var52.x4[3];
/* 23: addw */
- var66.x4[0] = var65.x4[0] + var52.x4[0];
- var66.x4[1] = var65.x4[1] + var52.x4[1];
- var66.x4[2] = var65.x4[2] + var52.x4[2];
- var66.x4[3] = var65.x4[3] + var52.x4[3];
- /* 24: addw */
- var67.x4[0] = var63.x4[0] + var50.x4[0];
- var67.x4[1] = var63.x4[1] + var50.x4[1];
- var67.x4[2] = var63.x4[2] + var50.x4[2];
- var67.x4[3] = var63.x4[3] + var50.x4[3];
- /* 25: divluw */
- var68.x4[0] =
- ((var67.x4[0] & 0xff) ==
- 0) ? 255 : ORC_CLAMP_UB (((orc_uint16) var66.x4[0]) /
- ((orc_uint16) var67.x4[0] & 0xff));
- var68.x4[1] =
- ((var67.x4[1] & 0xff) ==
- 0) ? 255 : ORC_CLAMP_UB (((orc_uint16) var66.x4[1]) /
- ((orc_uint16) var67.x4[1] & 0xff));
- var68.x4[2] =
- ((var67.x4[2] & 0xff) ==
- 0) ? 255 : ORC_CLAMP_UB (((orc_uint16) var66.x4[2]) /
- ((orc_uint16) var67.x4[2] & 0xff));
- var68.x4[3] =
- ((var67.x4[3] & 0xff) ==
- 0) ? 255 : ORC_CLAMP_UB (((orc_uint16) var66.x4[3]) /
- ((orc_uint16) var67.x4[3] & 0xff));
- /* 26: convwb */
- var69.x4[0] = var68.x4[0];
- var69.x4[1] = var68.x4[1];
- var69.x4[2] = var68.x4[2];
- var69.x4[3] = var68.x4[3];
- /* 28: andl */
- var70.i = var69.i & var42.i;
- /* 29: convwb */
- var71.x4[0] = var67.x4[0];
- var71.x4[1] = var67.x4[1];
- var71.x4[2] = var67.x4[2];
- var71.x4[3] = var67.x4[3];
- /* 31: andl */
- var72.i = var71.i & var43.i;
- /* 32: orl */
- var73.i = var70.i | var72.i;
- /* 33: storel */
- ptr0[i] = var73;
+ var66.x4[0] = var62.x4[0] + var50.x4[0];
+ var66.x4[1] = var62.x4[1] + var50.x4[1];
+ var66.x4[2] = var62.x4[2] + var50.x4[2];
+ var66.x4[3] = var62.x4[3] + var50.x4[3];
+ /* 24: divluw */
+ var67.x4[0] =
+ ((var66.x4[0] & 0xff) ==
+ 0) ? 255 : ORC_CLAMP_UB (((orc_uint16) var65.x4[0]) /
+ ((orc_uint16) var66.x4[0] & 0xff));
+ var67.x4[1] =
+ ((var66.x4[1] & 0xff) ==
+ 0) ? 255 : ORC_CLAMP_UB (((orc_uint16) var65.x4[1]) /
+ ((orc_uint16) var66.x4[1] & 0xff));
+ var67.x4[2] =
+ ((var66.x4[2] & 0xff) ==
+ 0) ? 255 : ORC_CLAMP_UB (((orc_uint16) var65.x4[2]) /
+ ((orc_uint16) var66.x4[2] & 0xff));
+ var67.x4[3] =
+ ((var66.x4[3] & 0xff) ==
+ 0) ? 255 : ORC_CLAMP_UB (((orc_uint16) var65.x4[3]) /
+ ((orc_uint16) var66.x4[3] & 0xff));
+ /* 25: convwb */
+ var68.x4[0] = var67.x4[0];
+ var68.x4[1] = var67.x4[1];
+ var68.x4[2] = var67.x4[2];
+ var68.x4[3] = var67.x4[3];
+ /* 27: andl */
+ var69.i = var68.i & var42.i;
+ /* 28: convwb */
+ var70.x4[0] = var66.x4[0];
+ var70.x4[1] = var66.x4[1];
+ var70.x4[2] = var66.x4[2];
+ var70.x4[3] = var66.x4[3];
+ /* 30: andl */
+ var71.i = var70.i & var43.i;
+ /* 31: orl */
+ var72.i = var69.i | var71.i;
+ /* 32: storel */
+ ptr0[i] = var72;
}
}
}
void
-orc_overlay_argb (guint8 * d1, int d1_stride, const guint8 * s1, int s1_stride,
- int p1, int n, int m)
+orc_overlay_argb (guint8 * ORC_RESTRICT d1, int d1_stride,
+ const guint8 * ORC_RESTRICT s1, int s1_stride, int p1, int n, int m)
{
OrcExecutor _ex, *ex = &_ex;
static int p_inited = 0;
@@ -1566,7 +1569,6 @@ orc_overlay_argb (guint8 * d1, int d1_stride, const guint8 * s1, int s1_stride,
if (!p_inited) {
orc_once_mutex_lock ();
if (!p_inited) {
- OrcCompileResult result;
p = orc_program_new ();
orc_program_set_2d (p);
@@ -1619,8 +1621,6 @@ orc_overlay_argb (guint8 * d1, int d1_stride, const guint8 * s1, int s1_stride,
ORC_VAR_D1);
orc_program_append_2 (p, "convwb", 0, ORC_VAR_T3, ORC_VAR_T2, ORC_VAR_D1,
ORC_VAR_D1);
- orc_program_append_2 (p, "convubw", 0, ORC_VAR_T2, ORC_VAR_T3, ORC_VAR_D1,
- ORC_VAR_D1);
orc_program_append_2 (p, "splatbl", 0, ORC_VAR_T7, ORC_VAR_T3, ORC_VAR_D1,
ORC_VAR_D1);
orc_program_append_2 (p, "convubw", 2, ORC_VAR_T6, ORC_VAR_T7, ORC_VAR_D1,
@@ -1652,7 +1652,7 @@ orc_overlay_argb (guint8 * d1, int d1_stride, const guint8 * s1, int s1_stride,
orc_program_append_2 (p, "storel", 0, ORC_VAR_D1, ORC_VAR_T1, ORC_VAR_D1,
ORC_VAR_D1);
- result = orc_program_compile (p);
+ orc_program_compile (p);
}
p_inited = TRUE;
orc_once_mutex_unlock ();
@@ -1676,8 +1676,8 @@ orc_overlay_argb (guint8 * d1, int d1_stride, const guint8 * s1, int s1_stride,
/* orc_overlay_bgra */
#ifdef DISABLE_ORC
void
-orc_overlay_bgra (guint8 * d1, int d1_stride, const guint8 * s1, int s1_stride,
- int p1, int n, int m)
+orc_overlay_bgra (guint8 * ORC_RESTRICT d1, int d1_stride,
+ const guint8 * ORC_RESTRICT s1, int s1_stride, int p1, int n, int m)
{
int i;
int j;
@@ -1703,8 +1703,8 @@ orc_overlay_bgra (guint8 * d1, int d1_stride, const guint8 * s1, int s1_stride,
orc_union32 var59;
orc_union16 var60;
orc_int8 var61;
- orc_union16 var62;
- orc_union32 var63;
+ orc_union32 var62;
+ orc_union64 var63;
orc_union64 var64;
orc_union64 var65;
orc_union64 var66;
@@ -1712,12 +1712,11 @@ orc_overlay_bgra (guint8 * d1, int d1_stride, const guint8 * s1, int s1_stride,
orc_union64 var68;
orc_union64 var69;
orc_union64 var70;
- orc_union64 var71;
+ orc_union32 var71;
orc_union32 var72;
orc_union32 var73;
orc_union32 var74;
orc_union32 var75;
- orc_union32 var76;
for (j = 0; j < m; j++) {
ptr0 = ORC_PTR_OFFSET (d1, d1_stride * j);
@@ -1730,9 +1729,9 @@ orc_overlay_bgra (guint8 * d1, int d1_stride, const guint8 * s1, int s1_stride,
var42.x4[3] = p1;
/* 11: loadpl */
var55.i = (int) 0xffffffff; /* -1 or 2.122e-314f */
- /* 29: loadpl */
+ /* 28: loadpl */
var43.i = (int) 0x00ffffff; /* 16777215 or 8.28905e-317f */
- /* 32: loadpl */
+ /* 31: loadpl */
var44.i = (int) 0xff000000; /* -16777216 or 2.11371e-314f */
for (i = 0; i < n; i++) {
@@ -1741,7 +1740,7 @@ orc_overlay_bgra (guint8 * d1, int d1_stride, const guint8 * s1, int s1_stride,
/* 1: shrul */
var46.i = ((orc_uint32) var45.i) >> 24;
/* 2: convlw */
- var47.i = var45.i;
+ var47.i = var46.i;
/* 3: convwb */
var48 = var47.i;
/* 4: splatbl */
@@ -1788,93 +1787,91 @@ orc_overlay_bgra (guint8 * d1, int d1_stride, const guint8 * s1, int s1_stride,
/* 15: shrul */
var59.i = ((orc_uint32) var58.i) >> 24;
/* 16: convlw */
- var60.i = var58.i;
+ var60.i = var59.i;
/* 17: convwb */
var61 = var60.i;
- /* 18: convubw */
- var62.i = (orc_uint8) var61;
- /* 19: splatbl */
- var63.i =
+ /* 18: splatbl */
+ var62.i =
((var61 & 0xff) << 24) | ((var61 & 0xff) << 16) | ((var61 & 0xff) <<
8) | (var61 & 0xff);
- /* 20: convubw */
- var64.x4[0] = (orc_uint8) var63.x4[0];
- var64.x4[1] = (orc_uint8) var63.x4[1];
- var64.x4[2] = (orc_uint8) var63.x4[2];
- var64.x4[3] = (orc_uint8) var63.x4[3];
- /* 21: mullw */
- var65.x4[0] = (var64.x4[0] * var57.x4[0]) & 0xffff;
- var65.x4[1] = (var64.x4[1] * var57.x4[1]) & 0xffff;
- var65.x4[2] = (var64.x4[2] * var57.x4[2]) & 0xffff;
- var65.x4[3] = (var64.x4[3] * var57.x4[3]) & 0xffff;
- /* 22: div255w */
- var66.x4[0] =
- ((orc_uint16) (((orc_uint16) (var65.x4[0] + 128)) +
- (((orc_uint16) (var65.x4[0] + 128)) >> 8))) >> 8;
- var66.x4[1] =
- ((orc_uint16) (((orc_uint16) (var65.x4[1] + 128)) +
- (((orc_uint16) (var65.x4[1] + 128)) >> 8))) >> 8;
- var66.x4[2] =
- ((orc_uint16) (((orc_uint16) (var65.x4[2] + 128)) +
- (((orc_uint16) (var65.x4[2] + 128)) >> 8))) >> 8;
- var66.x4[3] =
- ((orc_uint16) (((orc_uint16) (var65.x4[3] + 128)) +
- (((orc_uint16) (var65.x4[3] + 128)) >> 8))) >> 8;
- /* 23: convubw */
- var67.x4[0] = (orc_uint8) var58.x4[0];
- var67.x4[1] = (orc_uint8) var58.x4[1];
- var67.x4[2] = (orc_uint8) var58.x4[2];
- var67.x4[3] = (orc_uint8) var58.x4[3];
- /* 24: mullw */
- var68.x4[0] = (var67.x4[0] * var66.x4[0]) & 0xffff;
- var68.x4[1] = (var67.x4[1] * var66.x4[1]) & 0xffff;
- var68.x4[2] = (var67.x4[2] * var66.x4[2]) & 0xffff;
- var68.x4[3] = (var67.x4[3] * var66.x4[3]) & 0xffff;
+ /* 19: convubw */
+ var63.x4[0] = (orc_uint8) var62.x4[0];
+ var63.x4[1] = (orc_uint8) var62.x4[1];
+ var63.x4[2] = (orc_uint8) var62.x4[2];
+ var63.x4[3] = (orc_uint8) var62.x4[3];
+ /* 20: mullw */
+ var64.x4[0] = (var63.x4[0] * var57.x4[0]) & 0xffff;
+ var64.x4[1] = (var63.x4[1] * var57.x4[1]) & 0xffff;
+ var64.x4[2] = (var63.x4[2] * var57.x4[2]) & 0xffff;
+ var64.x4[3] = (var63.x4[3] * var57.x4[3]) & 0xffff;
+ /* 21: div255w */
+ var65.x4[0] =
+ ((orc_uint16) (((orc_uint16) (var64.x4[0] + 128)) +
+ (((orc_uint16) (var64.x4[0] + 128)) >> 8))) >> 8;
+ var65.x4[1] =
+ ((orc_uint16) (((orc_uint16) (var64.x4[1] + 128)) +
+ (((orc_uint16) (var64.x4[1] + 128)) >> 8))) >> 8;
+ var65.x4[2] =
+ ((orc_uint16) (((orc_uint16) (var64.x4[2] + 128)) +
+ (((orc_uint16) (var64.x4[2] + 128)) >> 8))) >> 8;
+ var65.x4[3] =
+ ((orc_uint16) (((orc_uint16) (var64.x4[3] + 128)) +
+ (((orc_uint16) (var64.x4[3] + 128)) >> 8))) >> 8;
+ /* 22: convubw */
+ var66.x4[0] = (orc_uint8) var58.x4[0];
+ var66.x4[1] = (orc_uint8) var58.x4[1];
+ var66.x4[2] = (orc_uint8) var58.x4[2];
+ var66.x4[3] = (orc_uint8) var58.x4[3];
+ /* 23: mullw */
+ var67.x4[0] = (var66.x4[0] * var65.x4[0]) & 0xffff;
+ var67.x4[1] = (var66.x4[1] * var65.x4[1]) & 0xffff;
+ var67.x4[2] = (var66.x4[2] * var65.x4[2]) & 0xffff;
+ var67.x4[3] = (var66.x4[3] * var65.x4[3]) & 0xffff;
+ /* 24: addw */
+ var68.x4[0] = var67.x4[0] + var54.x4[0];
+ var68.x4[1] = var67.x4[1] + var54.x4[1];
+ var68.x4[2] = var67.x4[2] + var54.x4[2];
+ var68.x4[3] = var67.x4[3] + var54.x4[3];
/* 25: addw */
- var69.x4[0] = var68.x4[0] + var54.x4[0];
- var69.x4[1] = var68.x4[1] + var54.x4[1];
- var69.x4[2] = var68.x4[2] + var54.x4[2];
- var69.x4[3] = var68.x4[3] + var54.x4[3];
- /* 26: addw */
- var70.x4[0] = var66.x4[0] + var52.x4[0];
- var70.x4[1] = var66.x4[1] + var52.x4[1];
- var70.x4[2] = var66.x4[2] + var52.x4[2];
- var70.x4[3] = var66.x4[3] + var52.x4[3];
- /* 27: divluw */
- var71.x4[0] =
- ((var70.x4[0] & 0xff) ==
- 0) ? 255 : ORC_CLAMP_UB (((orc_uint16) var69.x4[0]) /
- ((orc_uint16) var70.x4[0] & 0xff));
- var71.x4[1] =
- ((var70.x4[1] & 0xff) ==
- 0) ? 255 : ORC_CLAMP_UB (((orc_uint16) var69.x4[1]) /
- ((orc_uint16) var70.x4[1] & 0xff));
- var71.x4[2] =
- ((var70.x4[2] & 0xff) ==
- 0) ? 255 : ORC_CLAMP_UB (((orc_uint16) var69.x4[2]) /
- ((orc_uint16) var70.x4[2] & 0xff));
- var71.x4[3] =
- ((var70.x4[3] & 0xff) ==
- 0) ? 255 : ORC_CLAMP_UB (((orc_uint16) var69.x4[3]) /
- ((orc_uint16) var70.x4[3] & 0xff));
- /* 28: convwb */
- var72.x4[0] = var71.x4[0];
- var72.x4[1] = var71.x4[1];
- var72.x4[2] = var71.x4[2];
- var72.x4[3] = var71.x4[3];
- /* 30: andl */
- var73.i = var72.i & var43.i;
- /* 31: convwb */
- var74.x4[0] = var70.x4[0];
- var74.x4[1] = var70.x4[1];
- var74.x4[2] = var70.x4[2];
- var74.x4[3] = var70.x4[3];
- /* 33: andl */
- var75.i = var74.i & var44.i;
- /* 34: orl */
- var76.i = var73.i | var75.i;
- /* 35: storel */
- ptr0[i] = var76;
+ var69.x4[0] = var65.x4[0] + var52.x4[0];
+ var69.x4[1] = var65.x4[1] + var52.x4[1];
+ var69.x4[2] = var65.x4[2] + var52.x4[2];
+ var69.x4[3] = var65.x4[3] + var52.x4[3];
+ /* 26: divluw */
+ var70.x4[0] =
+ ((var69.x4[0] & 0xff) ==
+ 0) ? 255 : ORC_CLAMP_UB (((orc_uint16) var68.x4[0]) /
+ ((orc_uint16) var69.x4[0] & 0xff));
+ var70.x4[1] =
+ ((var69.x4[1] & 0xff) ==
+ 0) ? 255 : ORC_CLAMP_UB (((orc_uint16) var68.x4[1]) /
+ ((orc_uint16) var69.x4[1] & 0xff));
+ var70.x4[2] =
+ ((var69.x4[2] & 0xff) ==
+ 0) ? 255 : ORC_CLAMP_UB (((orc_uint16) var68.x4[2]) /
+ ((orc_uint16) var69.x4[2] & 0xff));
+ var70.x4[3] =
+ ((var69.x4[3] & 0xff) ==
+ 0) ? 255 : ORC_CLAMP_UB (((orc_uint16) var68.x4[3]) /
+ ((orc_uint16) var69.x4[3] & 0xff));
+ /* 27: convwb */
+ var71.x4[0] = var70.x4[0];
+ var71.x4[1] = var70.x4[1];
+ var71.x4[2] = var70.x4[2];
+ var71.x4[3] = var70.x4[3];
+ /* 29: andl */
+ var72.i = var71.i & var43.i;
+ /* 30: convwb */
+ var73.x4[0] = var69.x4[0];
+ var73.x4[1] = var69.x4[1];
+ var73.x4[2] = var69.x4[2];
+ var73.x4[3] = var69.x4[3];
+ /* 32: andl */
+ var74.i = var73.i & var44.i;
+ /* 33: orl */
+ var75.i = var72.i | var74.i;
+ /* 34: storel */
+ ptr0[i] = var75;
}
}
@@ -1910,8 +1907,8 @@ _backup_orc_overlay_bgra (OrcExecutor * ORC_RESTRICT ex)
orc_union32 var59;
orc_union16 var60;
orc_int8 var61;
- orc_union16 var62;
- orc_union32 var63;
+ orc_union32 var62;
+ orc_union64 var63;
orc_union64 var64;
orc_union64 var65;
orc_union64 var66;
@@ -1919,12 +1916,11 @@ _backup_orc_overlay_bgra (OrcExecutor * ORC_RESTRICT ex)
orc_union64 var68;
orc_union64 var69;
orc_union64 var70;
- orc_union64 var71;
+ orc_union32 var71;
orc_union32 var72;
orc_union32 var73;
orc_union32 var74;
orc_union32 var75;
- orc_union32 var76;
for (j = 0; j < m; j++) {
ptr0 = ORC_PTR_OFFSET (ex->arrays[0], ex->params[0] * j);
@@ -1937,9 +1933,9 @@ _backup_orc_overlay_bgra (OrcExecutor * ORC_RESTRICT ex)
var42.x4[3] = ex->params[24];
/* 11: loadpl */
var55.i = (int) 0xffffffff; /* -1 or 2.122e-314f */
- /* 29: loadpl */
+ /* 28: loadpl */
var43.i = (int) 0x00ffffff; /* 16777215 or 8.28905e-317f */
- /* 32: loadpl */
+ /* 31: loadpl */
var44.i = (int) 0xff000000; /* -16777216 or 2.11371e-314f */
for (i = 0; i < n; i++) {
@@ -1948,7 +1944,7 @@ _backup_orc_overlay_bgra (OrcExecutor * ORC_RESTRICT ex)
/* 1: shrul */
var46.i = ((orc_uint32) var45.i) >> 24;
/* 2: convlw */
- var47.i = var45.i;
+ var47.i = var46.i;
/* 3: convwb */
var48 = var47.i;
/* 4: splatbl */
@@ -1995,101 +1991,99 @@ _backup_orc_overlay_bgra (OrcExecutor * ORC_RESTRICT ex)
/* 15: shrul */
var59.i = ((orc_uint32) var58.i) >> 24;
/* 16: convlw */
- var60.i = var58.i;
+ var60.i = var59.i;
/* 17: convwb */
var61 = var60.i;
- /* 18: convubw */
- var62.i = (orc_uint8) var61;
- /* 19: splatbl */
- var63.i =
+ /* 18: splatbl */
+ var62.i =
((var61 & 0xff) << 24) | ((var61 & 0xff) << 16) | ((var61 & 0xff) <<
8) | (var61 & 0xff);
- /* 20: convubw */
- var64.x4[0] = (orc_uint8) var63.x4[0];
- var64.x4[1] = (orc_uint8) var63.x4[1];
- var64.x4[2] = (orc_uint8) var63.x4[2];
- var64.x4[3] = (orc_uint8) var63.x4[3];
- /* 21: mullw */
- var65.x4[0] = (var64.x4[0] * var57.x4[0]) & 0xffff;
- var65.x4[1] = (var64.x4[1] * var57.x4[1]) & 0xffff;
- var65.x4[2] = (var64.x4[2] * var57.x4[2]) & 0xffff;
- var65.x4[3] = (var64.x4[3] * var57.x4[3]) & 0xffff;
- /* 22: div255w */
- var66.x4[0] =
- ((orc_uint16) (((orc_uint16) (var65.x4[0] + 128)) +
- (((orc_uint16) (var65.x4[0] + 128)) >> 8))) >> 8;
- var66.x4[1] =
- ((orc_uint16) (((orc_uint16) (var65.x4[1] + 128)) +
- (((orc_uint16) (var65.x4[1] + 128)) >> 8))) >> 8;
- var66.x4[2] =
- ((orc_uint16) (((orc_uint16) (var65.x4[2] + 128)) +
- (((orc_uint16) (var65.x4[2] + 128)) >> 8))) >> 8;
- var66.x4[3] =
- ((orc_uint16) (((orc_uint16) (var65.x4[3] + 128)) +
- (((orc_uint16) (var65.x4[3] + 128)) >> 8))) >> 8;
- /* 23: convubw */
- var67.x4[0] = (orc_uint8) var58.x4[0];
- var67.x4[1] = (orc_uint8) var58.x4[1];
- var67.x4[2] = (orc_uint8) var58.x4[2];
- var67.x4[3] = (orc_uint8) var58.x4[3];
- /* 24: mullw */
- var68.x4[0] = (var67.x4[0] * var66.x4[0]) & 0xffff;
- var68.x4[1] = (var67.x4[1] * var66.x4[1]) & 0xffff;
- var68.x4[2] = (var67.x4[2] * var66.x4[2]) & 0xffff;
- var68.x4[3] = (var67.x4[3] * var66.x4[3]) & 0xffff;
+ /* 19: convubw */
+ var63.x4[0] = (orc_uint8) var62.x4[0];
+ var63.x4[1] = (orc_uint8) var62.x4[1];
+ var63.x4[2] = (orc_uint8) var62.x4[2];
+ var63.x4[3] = (orc_uint8) var62.x4[3];
+ /* 20: mullw */
+ var64.x4[0] = (var63.x4[0] * var57.x4[0]) & 0xffff;
+ var64.x4[1] = (var63.x4[1] * var57.x4[1]) & 0xffff;
+ var64.x4[2] = (var63.x4[2] * var57.x4[2]) & 0xffff;
+ var64.x4[3] = (var63.x4[3] * var57.x4[3]) & 0xffff;
+ /* 21: div255w */
+ var65.x4[0] =
+ ((orc_uint16) (((orc_uint16) (var64.x4[0] + 128)) +
+ (((orc_uint16) (var64.x4[0] + 128)) >> 8))) >> 8;
+ var65.x4[1] =
+ ((orc_uint16) (((orc_uint16) (var64.x4[1] + 128)) +
+ (((orc_uint16) (var64.x4[1] + 128)) >> 8))) >> 8;
+ var65.x4[2] =
+ ((orc_uint16) (((orc_uint16) (var64.x4[2] + 128)) +
+ (((orc_uint16) (var64.x4[2] + 128)) >> 8))) >> 8;
+ var65.x4[3] =
+ ((orc_uint16) (((orc_uint16) (var64.x4[3] + 128)) +
+ (((orc_uint16) (var64.x4[3] + 128)) >> 8))) >> 8;
+ /* 22: convubw */
+ var66.x4[0] = (orc_uint8) var58.x4[0];
+ var66.x4[1] = (orc_uint8) var58.x4[1];
+ var66.x4[2] = (orc_uint8) var58.x4[2];
+ var66.x4[3] = (orc_uint8) var58.x4[3];
+ /* 23: mullw */
+ var67.x4[0] = (var66.x4[0] * var65.x4[0]) & 0xffff;
+ var67.x4[1] = (var66.x4[1] * var65.x4[1]) & 0xffff;
+ var67.x4[2] = (var66.x4[2] * var65.x4[2]) & 0xffff;
+ var67.x4[3] = (var66.x4[3] * var65.x4[3]) & 0xffff;
+ /* 24: addw */
+ var68.x4[0] = var67.x4[0] + var54.x4[0];
+ var68.x4[1] = var67.x4[1] + var54.x4[1];
+ var68.x4[2] = var67.x4[2] + var54.x4[2];
+ var68.x4[3] = var67.x4[3] + var54.x4[3];
/* 25: addw */
- var69.x4[0] = var68.x4[0] + var54.x4[0];
- var69.x4[1] = var68.x4[1] + var54.x4[1];
- var69.x4[2] = var68.x4[2] + var54.x4[2];
- var69.x4[3] = var68.x4[3] + var54.x4[3];
- /* 26: addw */
- var70.x4[0] = var66.x4[0] + var52.x4[0];
- var70.x4[1] = var66.x4[1] + var52.x4[1];
- var70.x4[2] = var66.x4[2] + var52.x4[2];
- var70.x4[3] = var66.x4[3] + var52.x4[3];
- /* 27: divluw */
- var71.x4[0] =
- ((var70.x4[0] & 0xff) ==
- 0) ? 255 : ORC_CLAMP_UB (((orc_uint16) var69.x4[0]) /
- ((orc_uint16) var70.x4[0] & 0xff));
- var71.x4[1] =
- ((var70.x4[1] & 0xff) ==
- 0) ? 255 : ORC_CLAMP_UB (((orc_uint16) var69.x4[1]) /
- ((orc_uint16) var70.x4[1] & 0xff));
- var71.x4[2] =
- ((var70.x4[2] & 0xff) ==
- 0) ? 255 : ORC_CLAMP_UB (((orc_uint16) var69.x4[2]) /
- ((orc_uint16) var70.x4[2] & 0xff));
- var71.x4[3] =
- ((var70.x4[3] & 0xff) ==
- 0) ? 255 : ORC_CLAMP_UB (((orc_uint16) var69.x4[3]) /
- ((orc_uint16) var70.x4[3] & 0xff));
- /* 28: convwb */
- var72.x4[0] = var71.x4[0];
- var72.x4[1] = var71.x4[1];
- var72.x4[2] = var71.x4[2];
- var72.x4[3] = var71.x4[3];
- /* 30: andl */
- var73.i = var72.i & var43.i;
- /* 31: convwb */
- var74.x4[0] = var70.x4[0];
- var74.x4[1] = var70.x4[1];
- var74.x4[2] = var70.x4[2];
- var74.x4[3] = var70.x4[3];
- /* 33: andl */
- var75.i = var74.i & var44.i;
- /* 34: orl */
- var76.i = var73.i | var75.i;
- /* 35: storel */
- ptr0[i] = var76;
+ var69.x4[0] = var65.x4[0] + var52.x4[0];
+ var69.x4[1] = var65.x4[1] + var52.x4[1];
+ var69.x4[2] = var65.x4[2] + var52.x4[2];
+ var69.x4[3] = var65.x4[3] + var52.x4[3];
+ /* 26: divluw */
+ var70.x4[0] =
+ ((var69.x4[0] & 0xff) ==
+ 0) ? 255 : ORC_CLAMP_UB (((orc_uint16) var68.x4[0]) /
+ ((orc_uint16) var69.x4[0] & 0xff));
+ var70.x4[1] =
+ ((var69.x4[1] & 0xff) ==
+ 0) ? 255 : ORC_CLAMP_UB (((orc_uint16) var68.x4[1]) /
+ ((orc_uint16) var69.x4[1] & 0xff));
+ var70.x4[2] =
+ ((var69.x4[2] & 0xff) ==
+ 0) ? 255 : ORC_CLAMP_UB (((orc_uint16) var68.x4[2]) /
+ ((orc_uint16) var69.x4[2] & 0xff));
+ var70.x4[3] =
+ ((var69.x4[3] & 0xff) ==
+ 0) ? 255 : ORC_CLAMP_UB (((orc_uint16) var68.x4[3]) /
+ ((orc_uint16) var69.x4[3] & 0xff));
+ /* 27: convwb */
+ var71.x4[0] = var70.x4[0];
+ var71.x4[1] = var70.x4[1];
+ var71.x4[2] = var70.x4[2];
+ var71.x4[3] = var70.x4[3];
+ /* 29: andl */
+ var72.i = var71.i & var43.i;
+ /* 30: convwb */
+ var73.x4[0] = var69.x4[0];
+ var73.x4[1] = var69.x4[1];
+ var73.x4[2] = var69.x4[2];
+ var73.x4[3] = var69.x4[3];
+ /* 32: andl */
+ var74.i = var73.i & var44.i;
+ /* 33: orl */
+ var75.i = var72.i | var74.i;
+ /* 34: storel */
+ ptr0[i] = var75;
}
}
}
void
-orc_overlay_bgra (guint8 * d1, int d1_stride, const guint8 * s1, int s1_stride,
- int p1, int n, int m)
+orc_overlay_bgra (guint8 * ORC_RESTRICT d1, int d1_stride,
+ const guint8 * ORC_RESTRICT s1, int s1_stride, int p1, int n, int m)
{
OrcExecutor _ex, *ex = &_ex;
static int p_inited = 0;
@@ -2099,7 +2093,6 @@ orc_overlay_bgra (guint8 * d1, int d1_stride, const guint8 * s1, int s1_stride,
if (!p_inited) {
orc_once_mutex_lock ();
if (!p_inited) {
- OrcCompileResult result;
p = orc_program_new ();
orc_program_set_2d (p);
@@ -2128,7 +2121,7 @@ orc_overlay_bgra (guint8 * d1, int d1_stride, const guint8 * s1, int s1_stride,
ORC_VAR_D1);
orc_program_append_2 (p, "shrul", 0, ORC_VAR_T2, ORC_VAR_T1, ORC_VAR_C4,
ORC_VAR_D1);
- orc_program_append_2 (p, "convlw", 0, ORC_VAR_T3, ORC_VAR_T1, ORC_VAR_D1,
+ orc_program_append_2 (p, "convlw", 0, ORC_VAR_T3, ORC_VAR_T2, ORC_VAR_D1,
ORC_VAR_D1);
orc_program_append_2 (p, "convwb", 0, ORC_VAR_T4, ORC_VAR_T3, ORC_VAR_D1,
ORC_VAR_D1);
@@ -2154,12 +2147,10 @@ orc_overlay_bgra (guint8 * d1, int d1_stride, const guint8 * s1, int s1_stride,
ORC_VAR_D1);
orc_program_append_2 (p, "shrul", 0, ORC_VAR_T2, ORC_VAR_T1, ORC_VAR_C4,
ORC_VAR_D1);
- orc_program_append_2 (p, "convlw", 0, ORC_VAR_T3, ORC_VAR_T1, ORC_VAR_D1,
+ orc_program_append_2 (p, "convlw", 0, ORC_VAR_T3, ORC_VAR_T2, ORC_VAR_D1,
ORC_VAR_D1);
orc_program_append_2 (p, "convwb", 0, ORC_VAR_T4, ORC_VAR_T3, ORC_VAR_D1,
ORC_VAR_D1);
- orc_program_append_2 (p, "convubw", 0, ORC_VAR_T3, ORC_VAR_T4, ORC_VAR_D1,
- ORC_VAR_D1);
orc_program_append_2 (p, "splatbl", 0, ORC_VAR_T8, ORC_VAR_T4, ORC_VAR_D1,
ORC_VAR_D1);
orc_program_append_2 (p, "convubw", 2, ORC_VAR_T7, ORC_VAR_T8, ORC_VAR_D1,
@@ -2191,7 +2182,7 @@ orc_overlay_bgra (guint8 * d1, int d1_stride, const guint8 * s1, int s1_stride,
orc_program_append_2 (p, "storel", 0, ORC_VAR_D1, ORC_VAR_T1, ORC_VAR_D1,
ORC_VAR_D1);
- result = orc_program_compile (p);
+ orc_program_compile (p);
}
p_inited = TRUE;
orc_once_mutex_unlock ();
diff --git a/gst/videomixer/blendorc-dist.h b/gst/videomixer/blendorc-dist.h
index abc9aefd1..9346540fb 100644
--- a/gst/videomixer/blendorc-dist.h
+++ b/gst/videomixer/blendorc-dist.h
@@ -58,13 +58,22 @@ typedef union { orc_int16 i; orc_int8 x2[2]; } orc_union16;
typedef union { orc_int32 i; float f; orc_int16 x2[2]; orc_int8 x4[4]; } orc_union32;
typedef union { orc_int64 i; double f; orc_int32 x2[2]; float x2f[2]; orc_int16 x4[4]; } orc_union64;
#endif
-void orc_splat_u32 (guint32 * d1, int p1, int n);
-void orc_memcpy_u32 (guint32 * d1, const guint32 * s1, int n);
-void orc_blend_u8 (guint8 * d1, int d1_stride, const guint8 * s1, int s1_stride, int p1, int n, int m);
-void orc_blend_argb (guint8 * d1, int d1_stride, const guint8 * s1, int s1_stride, int p1, int n, int m);
-void orc_blend_bgra (guint8 * d1, int d1_stride, const guint8 * s1, int s1_stride, int p1, int n, int m);
-void orc_overlay_argb (guint8 * d1, int d1_stride, const guint8 * s1, int s1_stride, int p1, int n, int m);
-void orc_overlay_bgra (guint8 * d1, int d1_stride, const guint8 * s1, int s1_stride, int p1, int n, int m);
+#ifndef ORC_RESTRICT
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+#define ORC_RESTRICT restrict
+#elif defined(__GNUC__) && __GNUC__ >= 4
+#define ORC_RESTRICT __restrict__
+#else
+#define ORC_RESTRICT
+#endif
+#endif
+void orc_splat_u32 (guint32 * ORC_RESTRICT d1, int p1, int n);
+void orc_memcpy_u32 (guint32 * ORC_RESTRICT d1, const guint32 * ORC_RESTRICT s1, int n);
+void orc_blend_u8 (guint8 * ORC_RESTRICT d1, int d1_stride, const guint8 * ORC_RESTRICT s1, int s1_stride, int p1, int n, int m);
+void orc_blend_argb (guint8 * ORC_RESTRICT d1, int d1_stride, const guint8 * ORC_RESTRICT s1, int s1_stride, int p1, int n, int m);
+void orc_blend_bgra (guint8 * ORC_RESTRICT d1, int d1_stride, const guint8 * ORC_RESTRICT s1, int s1_stride, int p1, int n, int m);
+void orc_overlay_argb (guint8 * ORC_RESTRICT d1, int d1_stride, const guint8 * ORC_RESTRICT s1, int s1_stride, int p1, int n, int m);
+void orc_overlay_bgra (guint8 * ORC_RESTRICT d1, int d1_stride, const guint8 * ORC_RESTRICT s1, int s1_stride, int p1, int n, int m);
#ifdef __cplusplus
}
diff --git a/gst/videomixer/blendorc.orc b/gst/videomixer/blendorc.orc
index a28451325..91403456b 100644
--- a/gst/videomixer/blendorc.orc
+++ b/gst/videomixer/blendorc.orc
@@ -132,7 +132,6 @@ x4 subw alpha_s_inv, alpha_s_inv, alpha_s
loadl t, d
convlw tw, t
convwb tb, tw
-convubw tw, tb
splatbl a, tb
x4 convubw alpha_d, a
x4 mullw alpha_d, alpha_d, alpha_s_inv
@@ -179,7 +178,7 @@ storel d, t
# calc source alpha as alpha_s = alpha_s * alpha / 256
loadl t, s
shrul t2, t, 24
-convlw tw, t
+convlw tw, t2
convwb tb, tw
splatbl a, tb
x4 convubw alpha_s, a
@@ -194,9 +193,8 @@ x4 convubw alpha_s_inv, a
x4 subw alpha_s_inv, alpha_s_inv, alpha_s
loadl t, d
shrul t2, t, 24
-convlw tw, t
+convlw tw, t2
convwb tb, tw
-convubw tw, tb
splatbl a, tb
x4 convubw alpha_d, a
x4 mullw alpha_d, alpha_d, alpha_s_inv
diff --git a/gst/videomixer/gstcollectpads2.c b/gst/videomixer/gstcollectpads2.c
index 058a064a0..df8dd5171 100644
--- a/gst/videomixer/gstcollectpads2.c
+++ b/gst/videomixer/gstcollectpads2.c
@@ -1198,7 +1198,7 @@ gst_collect_pads2_set_waiting (GstCollectPads2 * pads, GstCollectData2 * data,
/* Do something only on a change and if not locked */
if (!GST_COLLECT_PADS2_STATE_IS_SET (data, GST_COLLECT_PADS2_STATE_LOCKED) &&
(GST_COLLECT_PADS2_STATE_IS_SET (data, GST_COLLECT_PADS2_STATE_WAITING) !=
- ! !waiting)) {
+ !!waiting)) {
/* Set waiting state for this pad */
if (waiting)
GST_COLLECT_PADS2_STATE_SET (data, GST_COLLECT_PADS2_STATE_WAITING);
@@ -1759,7 +1759,6 @@ gst_collect_pads2_chain (GstPad * pad, GstBuffer * buffer)
{
GstCollectData2 *data;
GstCollectPads2 *pads;
- guint64 size;
GstFlowReturn ret;
GstBuffer **buffer_p;
guint32 cookie;
@@ -1782,8 +1781,6 @@ gst_collect_pads2_chain (GstPad * pad, GstBuffer * buffer)
prepare_buffer_user_data = pads->prepare_buffer_user_data;
GST_OBJECT_UNLOCK (pads);
- size = GST_BUFFER_SIZE (buffer);
-
GST_COLLECT_PADS2_STREAM_LOCK (pads);
/* if not started, bail out */
if (G_UNLIKELY (!pads->started))
diff --git a/gst/videomixer/videomixer2.c b/gst/videomixer/videomixer2.c
index e7f6ba857..76bbe5924 100644
--- a/gst/videomixer/videomixer2.c
+++ b/gst/videomixer/videomixer2.c
@@ -361,13 +361,11 @@ static GstCaps *
gst_videomixer2_pad_sink_getcaps (GstPad * pad)
{
GstVideoMixer2 *mix;
- GstVideoMixer2Pad *mixpad;
GstCaps *srccaps;
GstStructure *s;
gint i, n;
mix = GST_VIDEO_MIXER2 (gst_pad_get_parent (pad));
- mixpad = GST_VIDEO_MIXER2_PAD (pad);
srccaps = gst_pad_get_fixed_caps_func (GST_PAD (mix->srcpad));
srccaps = gst_caps_make_writable (srccaps);
@@ -1584,7 +1582,6 @@ gst_videomixer2_sink_prepare_buffer (GstCollectPads2 * pads,
GstVideoMixer2Pad *pad = GST_VIDEO_MIXER2_PAD (data->pad);
GstVideoMixer2Collect *mixcol = pad->mixcol;
GstClockTime start_time, end_time;
- gint64 last_stop;
start_time = GST_BUFFER_TIMESTAMP (buf);
if (start_time == -1) {
@@ -1616,10 +1613,6 @@ gst_videomixer2_sink_prepare_buffer (GstCollectPads2 * pads,
end_time *= mix->segment.abs_rate;
}
- last_stop = mix->segment.last_stop;
- if (mix->segment.last_stop == -1)
- last_stop = mix->segment.start;
-
if (mixcol->buffer != NULL && end_time < mixcol->end_time) {
return GST_COLLECT_PADS2_FLOW_DROP;
}
diff --git a/gst/wavenc/Makefile.am b/gst/wavenc/Makefile.am
index bdfc187d4..a213b0075 100644
--- a/gst/wavenc/Makefile.am
+++ b/gst/wavenc/Makefile.am
@@ -12,3 +12,17 @@ libgstwavenc_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
libgstwavenc_la_LIBTOOLFLAGS = --tag=disable-static
noinst_HEADERS = gstwavenc.h
+
+Android.mk: Makefile.am $(BUILT_SOURCES)
+ androgenizer \
+ -:PROJECT libgstwavenc -:SHARED libgstwavenc \
+ -:TAGS eng debug \
+ -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
+ -:SOURCES $(libgstwavenc_la_SOURCES) \
+ -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstwavenc_la_CFLAGS) \
+ -:LDFLAGS $(libgstwavenc_la_LDFLAGS) \
+ $(libgstwavenc_la_LIBADD) \
+ -ldl \
+ -:PASSTHROUGH LOCAL_ARM_MODE:=arm \
+ LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \
+ > $@
diff --git a/gst/wavparse/Makefile.am b/gst/wavparse/Makefile.am
index cd3e48721..24d3896c7 100644
--- a/gst/wavparse/Makefile.am
+++ b/gst/wavparse/Makefile.am
@@ -17,3 +17,17 @@ libgstwavparse_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
libgstwavparse_la_LIBTOOLFLAGS = --tag=disable-static
noinst_HEADERS = gstwavparse.h
+
+Android.mk: Makefile.am $(BUILT_SOURCES)
+ androgenizer \
+ -:PROJECT libgstwavparse -:SHARED libgstwavparse \
+ -:TAGS eng debug \
+ -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
+ -:SOURCES $(libgstwavparse_la_SOURCES) \
+ -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstwavparse_la_CFLAGS) \
+ -:LDFLAGS $(libgstwavparse_la_LDFLAGS) \
+ $(libgstwavparse_la_LIBADD) \
+ -ldl \
+ -:PASSTHROUGH LOCAL_ARM_MODE:=arm \
+ LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \
+ > $@
diff --git a/gst/y4m/Makefile.am b/gst/y4m/Makefile.am
index 4415e9e22..3548d8d2c 100644
--- a/gst/y4m/Makefile.am
+++ b/gst/y4m/Makefile.am
@@ -8,3 +8,17 @@ libgsty4menc_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
libgsty4menc_la_LIBTOOLFLAGS = --tag=disable-static
noinst_HEADERS = gsty4mencode.h
+
+Android.mk: Makefile.am $(BUILT_SOURCES)
+ androgenizer \
+ -:PROJECT libgsty4menc -:SHARED libgsty4menc \
+ -:TAGS eng debug \
+ -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
+ -:SOURCES $(libgsty4menc_la_SOURCES) \
+ -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgsty4menc_la_CFLAGS) \
+ -:LDFLAGS $(libgsty4menc_la_LDFLAGS) \
+ $(libgsty4menc_la_LIBADD) \
+ -ldl \
+ -:PASSTHROUGH LOCAL_ARM_MODE:=arm \
+ LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \
+ > $@
diff --git a/gst/y4m/gsty4mencode.c b/gst/y4m/gsty4mencode.c
index aba6ab785..4adaa5a1a 100644
--- a/gst/y4m/gsty4mencode.c
+++ b/gst/y4m/gsty4mencode.c
@@ -306,7 +306,7 @@ static void
gst_y4m_encode_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec)
{
- GstY4mEncode *filter;
+ GstY4mEncode G_GNUC_UNUSED *filter;
g_return_if_fail (GST_IS_Y4M_ENCODE (object));
filter = GST_Y4M_ENCODE (object);
@@ -321,7 +321,7 @@ static void
gst_y4m_encode_get_property (GObject * object, guint prop_id, GValue * value,
GParamSpec * pspec)
{
- GstY4mEncode *filter;
+ GstY4mEncode G_GNUC_UNUSED *filter;
g_return_if_fail (GST_IS_Y4M_ENCODE (object));
filter = GST_Y4M_ENCODE (object);
diff --git a/po/POTFILES.in b/po/POTFILES.in
index ea9a35d8e..5424a03bf 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -9,7 +9,7 @@ ext/wavpack/gstwavpackparse.c
gconf/gstreamer.schemas.in
gst/avi/gstavidemux.c
gst/avi/gstavimux.c
-gst/qtdemux/qtdemux.c
+gst/quicktime/qtdemux.c
gst/rtsp/gstrtspsrc.c
gst/wavparse/gstwavparse.c
sys/oss/gstossmixer.c
diff --git a/po/bg.po b/po/bg.po
index da3786aa9..5cad58ee2 100644
--- a/po/bg.po
+++ b/po/bg.po
@@ -1,15 +1,15 @@
# Bulgarian translation of gst-plugins-good.
-# Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+# Copyright (C) 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
# This file is distributed under the same license as the gst-plugins-good package.
-# Alexander Shopov <ash@kambanaria.org>, 2007, 2008, 2009, 2010.
+# Alexander Shopov <ash@kambanaria.org>, 2007, 2008, 2009, 2010, 2011.
#
#
msgid ""
msgstr ""
-"Project-Id-Version: gst-plugins-good 0.10.25.3\n"
+"Project-Id-Version: gst-plugins-good 0.10.26.2\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-01-07 01:15+0000\n"
-"PO-Revision-Date: 2010-11-04 14:23+0200\n"
+"POT-Creation-Date: 2011-04-16 16:25+0100\n"
+"PO-Revision-Date: 2011-01-15 16:44+0200\n"
"Last-Translator: Alexander Shopov <ash@kambanaria.org>\n"
"Language-Team: Bulgarian <dict@fsa-bg.org>\n"
"Language: bg\n"
@@ -73,7 +73,7 @@ msgid "This file is corrupt and cannot be played."
msgstr "Този файл е повреден и не може да бъде изпълнен."
msgid "Invalid atom size."
-msgstr ""
+msgstr "Неправилен размер на атом."
msgid "This file is incomplete and cannot be played."
msgstr "Този файл е непълен и не може да бъде изпълнен."
@@ -630,15 +630,16 @@ msgstr ""
msgid "Failed to set input %d on device %s."
msgstr "Неуспех при задаването на вход %d на устройство „%s“."
-#, fuzzy, c-format
+#, c-format
msgid ""
"Failed to get current output on device '%s'. May be it is a radio device"
msgstr ""
-"Неуспех при получаването на текущия вход на устройство „%s“. Може би е радио."
+"Неуспех при получаването на текущия изход на устройство „%s“. Може би е "
+"радио."
-#, fuzzy, c-format
+#, c-format
msgid "Failed to set output %d on device %s."
-msgstr "Неуспех при задаването на вход %d на устройство „%s“."
+msgstr "Неуспех при задаването на изход %d на устройство „%s“."
#, c-format
msgid "Could not enqueue buffers in device '%s'."
diff --git a/po/cs.po b/po/cs.po
index d91a5ee22..f6729e36d 100644
--- a/po/cs.po
+++ b/po/cs.po
@@ -1,15 +1,15 @@
# Czech translation of gst-plugins-good.
-# Copyright (C) 2007, 2008, 2009, 2010 the author(s) of gst-plugins-good.
+# Copyright (C) 2007, 2008, 2009, 2010, 2011 the author(s) of gst-plugins-good.
# Copyright (C) 2004 Miloslav Trmac <mitr@volny.cz>.
# This file is put in the public domain.
# Miloslav Trmac <mitr@volny.cz>, 2004.
-# Petr Kovar <pknbe@volny.cz>, 2007, 2008, 2009, 2010.
+# Petr Kovar <pknbe@volny.cz>, 2007, 2008, 2009, 2010, 2011.
msgid ""
msgstr ""
-"Project-Id-Version: gst-plugins-good-0.10.25.3\n"
+"Project-Id-Version: gst-plugins-good-0.10.26.2\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-01-07 01:15+0000\n"
-"PO-Revision-Date: 2010-10-31 10:21+0100\n"
+"POT-Creation-Date: 2011-04-16 16:25+0100\n"
+"PO-Revision-Date: 2011-01-12 23:07+0100\n"
"Last-Translator: Petr Kovar <pknbe@volny.cz>\n"
"Language-Team: Czech <translation-team-cs@lists.sourceforge.net>\n"
"Language: cs\n"
@@ -74,7 +74,7 @@ msgid "This file is corrupt and cannot be played."
msgstr "Tento soubor je poškozen a nelze jej přehrát."
msgid "Invalid atom size."
-msgstr ""
+msgstr "Atom - neplatná velikost."
msgid "This file is incomplete and cannot be played."
msgstr "Tento soubor není úplný a nelze jej přehrát."
@@ -632,16 +632,16 @@ msgstr ""
msgid "Failed to set input %d on device %s."
msgstr "Nezdařilo se nastavení vstupu \"%d\" na zařízení \"%s\"."
-#, fuzzy, c-format
+#, c-format
msgid ""
"Failed to get current output on device '%s'. May be it is a radio device"
msgstr ""
-"Nezdařilo se získání aktuálního vstupu na zařízení \"%s\". Možná se jedná o "
-"radiopřijímač."
+"Nezdařilo se získání aktuálního výstupu na zařízení \"%s\". Možná se jedná o "
+"radiopřijímač"
-#, fuzzy, c-format
+#, c-format
msgid "Failed to set output %d on device %s."
-msgstr "Nezdařilo se nastavení vstupu \"%d\" na zařízení \"%s\"."
+msgstr "Nezdařilo se nastavení výstupu %d na zařízení %s."
#, c-format
msgid "Could not enqueue buffers in device '%s'."
diff --git a/po/de.po b/po/de.po
index 12e2c1328..211de3bde 100644
--- a/po/de.po
+++ b/po/de.po
@@ -8,14 +8,14 @@
# Pipeline = Weiterleitung
# Stream = Strom
# mixer =
-# Christian Kirbach <christian.kirbach@googlemail.com>, 2010.
+# Christian Kirbach <christian.kirbach@googlemail.com>, 2010, 2011.
#
msgid ""
msgstr ""
-"Project-Id-Version: gst-plugins-good 0.10.25.3\n"
+"Project-Id-Version: gst-plugins-good 0.10.26.2\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-01-07 01:15+0000\n"
-"PO-Revision-Date: 2010-10-25 00:33+0200\n"
+"POT-Creation-Date: 2011-04-16 16:25+0100\n"
+"PO-Revision-Date: 2011-01-21 22:36+0100\n"
"Last-Translator: Christian Kirbach <christian.kirbach@googlemail.com>\n"
"Language-Team: German <translation-team-de@lists.sourceforge.net>\n"
"Language: de\n"
@@ -83,7 +83,7 @@ msgid "This file is corrupt and cannot be played."
msgstr "Diese Datei ist beschädigt und kann nicht wiedergegeben werden."
msgid "Invalid atom size."
-msgstr ""
+msgstr "Ungültige Atom-Größe."
msgid "This file is incomplete and cannot be played."
msgstr "Diese Datei ist unvollständig und kann nicht wiedergegeben werden."
@@ -640,23 +640,23 @@ msgstr ""
msgid "Failed to get current input on device '%s'. May be it is a radio device"
msgstr ""
"Auslesen der aktuellen Eingabe auf dem Gerät »%s« schlug fehl. Vielleicht "
-"ist es ein Radiogerät."
+"ist es ein Funkgerät."
#, c-format
msgid "Failed to set input %d on device %s."
msgstr "Festlegen der Eingabe »%d« des Geräts »%s« schlug fehl."
# Sendegerät sicherlich nicht, eben eher ein Radio. Warum diese Fehlermeldung beie einem Radiogerät kommen könnte, weiß ich allerdings auch nicht.
-#, fuzzy, c-format
+#, c-format
msgid ""
"Failed to get current output on device '%s'. May be it is a radio device"
msgstr ""
-"Auslesen der aktuellen Eingabe auf dem Gerät »%s« schlug fehl. Vielleicht "
-"ist es ein Radiogerät."
+"Auslesen der aktuellen Ausgabe des Geräts »%s« schlug fehl. Vielleicht ist "
+"es ein Funkgerät."
-#, fuzzy, c-format
+#, c-format
msgid "Failed to set output %d on device %s."
-msgstr "Festlegen der Eingabe »%d« des Geräts »%s« schlug fehl."
+msgstr "Festlegen der Ausgabe »%d« des Geräts »%s« schlug fehl."
#, c-format
msgid "Could not enqueue buffers in device '%s'."
diff --git a/po/es.po b/po/es.po
index bb8ac8a2a..8d6aa7a22 100644
--- a/po/es.po
+++ b/po/es.po
@@ -1,14 +1,14 @@
-# translation of gst-plugins-good-0.10.25.3.po to Español
+# translation of gst-plugins-good-0.10.26.2.po to Español
# spanish translation for gst-plugins-good
# This file is put in the public domain.
-# Jorge González González <aloriel@gmail.com>, 2007, 2008, 2009, 2010.
+# Jorge González González <aloriel@gmail.com>, 2007, 2008, 2009, 2010, 2011.
#
msgid ""
msgstr ""
-"Project-Id-Version: gst-plugins-good 0.10.25.3\n"
+"Project-Id-Version: gst-plugins-good 0.10.26.2\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-01-07 01:15+0000\n"
-"PO-Revision-Date: 2010-11-01 18:05+0100\n"
+"POT-Creation-Date: 2011-04-16 16:25+0100\n"
+"PO-Revision-Date: 2011-02-12 18:30+0100\n"
"Last-Translator: Jorge González González <aloriel@gmail.com>\n"
"Language-Team: Spanish <es@li.org>\n"
"Language: es\n"
@@ -74,7 +74,7 @@ msgid "This file is corrupt and cannot be played."
msgstr "Este archivo está corrupto y no se puede reproducir."
msgid "Invalid atom size."
-msgstr ""
+msgstr "El tamaño atom no es válido."
msgid "This file is incomplete and cannot be played."
msgstr "Este archivo está incompleto y no se puede reproducir."
@@ -639,16 +639,16 @@ msgstr ""
msgid "Failed to set input %d on device %s."
msgstr "Falló al establecer la entrada %d en el dispositivo %s."
-#, fuzzy, c-format
+#, c-format
msgid ""
"Failed to get current output on device '%s'. May be it is a radio device"
msgstr ""
-"Falló al obtener la entrada actual en el dispositivo «%s». Quizá sea un "
+"Falló al obtener la salida actual en el dispositivo «%s». Quizá sea un "
"dispositivo de radio."
-#, fuzzy, c-format
+#, c-format
msgid "Failed to set output %d on device %s."
-msgstr "Falló al establecer la entrada %d en el dispositivo %s."
+msgstr "Falló al establecer la salida %d en el dispositivo %s."
#, c-format
msgid "Could not enqueue buffers in device '%s'."
diff --git a/po/id.po b/po/id.po
index ab9e8132d..872295eec 100644
--- a/po/id.po
+++ b/po/id.po
@@ -1,14 +1,14 @@
# Indonesian translations for gst-plugins-good package.
# This file is put in the public domain.
#
-# Andhika Padmawan <andhika.padmawan@gmail.com>, 2010.
+# Andhika Padmawan <andhika.padmawan@gmail.com>, 2011.
#
msgid ""
msgstr ""
-"Project-Id-Version: gst-plugins-good 0.10.23.2\n"
+"Project-Id-Version: gst-plugins-good 0.10.26.2\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-01-07 01:15+0000\n"
-"PO-Revision-Date: 2010-06-29 22:42+0700\n"
+"POT-Creation-Date: 2011-04-16 16:25+0100\n"
+"PO-Revision-Date: 2011-02-26 18:09+0700\n"
"Last-Translator: Andhika Padmawan <andhika.padmawan@gmail.com>\n"
"Language-Team: Indonesian <translation-team-id@lists.sourceforge.net>\n"
"Language: id\n"
@@ -36,30 +36,28 @@ msgstr "Gagal untuk mengawasandi citra JPEG"
msgid "Could not connect to server"
msgstr "Tak dapat menghubungi server"
-#, fuzzy
msgid "Server does not support seeking."
-msgstr "Divais '%s' tak mendukung penangkap video"
+msgstr "Server tidak mendukung pencarian."
-#, fuzzy
msgid "Could not resolve server name."
-msgstr "Tak dapat menghubungi server"
+msgstr "Tak dapat menemukan nama server."
-#, fuzzy
msgid "Could not establish connection to server."
-msgstr "Tak dapat membangun koneksi ke server suara"
+msgstr "Tak dapat membangun koneksi ke server."
msgid "Secure connection setup failed."
-msgstr ""
+msgstr "Pengaturan koneksi aman gagal."
msgid ""
"A network error occured, or the server closed the connection unexpectedly."
msgstr ""
+"Terjadi sebuah galat jaringan, atau server menutup koneksi secara tiba-tiba."
msgid "Server sent bad data."
-msgstr ""
+msgstr "Server mengirim data rusak."
msgid "No URL set."
-msgstr ""
+msgstr "Tak ada URL yang ditentukan."
msgid "No or invalid input audio, AVI stream will be corrupt."
msgstr "Masukan audio tidak ada atau tidak sah, arus AVI akan rusak."
@@ -74,7 +72,7 @@ msgid "This file is corrupt and cannot be played."
msgstr "Berkas ini rusak dan tak dapat diputar."
msgid "Invalid atom size."
-msgstr ""
+msgstr "Ukuran atom tidak sah."
msgid "This file is incomplete and cannot be played."
msgstr "Berkas ini tidak lengkap dan tak dapat diputar."
@@ -626,15 +624,15 @@ msgstr ""
msgid "Failed to set input %d on device %s."
msgstr "Gagal mengatur masukan %d di divais %s."
-#, fuzzy, c-format
+#, c-format
msgid ""
"Failed to get current output on device '%s'. May be it is a radio device"
msgstr ""
-"Gagal mendapatkan masukan terkini di divais '%s'. Mungkin itu divais radio"
+"Gagal mendapatkan keluaran terkini di divais '%s'. Mungkin itu divais radio"
-#, fuzzy, c-format
+#, c-format
msgid "Failed to set output %d on device %s."
-msgstr "Gagal mengatur masukan %d di divais %s."
+msgstr "Gagal mengatur keluaran %d di divais %s."
#, c-format
msgid "Could not enqueue buffers in device '%s'."
diff --git a/po/sl.po b/po/sl.po
index cb587ace1..9ee082238 100644
--- a/po/sl.po
+++ b/po/sl.po
@@ -1,17 +1,17 @@
-# -*- mode:po; coding:utf-8; -*- Slovenian message catalogue for gst-plugins-good.
+# Slovenian translation for gst-plugins-good.
+# Copyright (C) 2005 - 2011 Free Software Foundation, Inc.
# This file is distributed under the same license as the gst-plugins-good package.
-# Copyright (C) 2005 Free Software Foundation, Inc.
-#
# Robert Horvat <robi@hipnos.net>, 2010.
# Matej Urbančič <matej.urban@gmail.com>, 2010 - 2011.
+# Klemen Košir <klemen.kosir@gmx.com>, 2011.
#
msgid ""
msgstr ""
"Project-Id-Version: gst-plugins-good 0.10.26.2\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-01-11 19:32+0000\n"
-"PO-Revision-Date: 2011-01-07 20:28+0100\n"
-"Last-Translator: Matej Urbančič <matej.urban@gmail.com>\n"
+"POT-Creation-Date: 2011-04-16 16:25+0100\n"
+"PO-Revision-Date: 2011-03-12 18:35+0100\n"
+"Last-Translator: Klemen Košir <klemen.kosir@gmx.com>\n"
"Language-Team: Slovenian <translation-team-sl@lists.sourceforge.net>\n"
"Language: sl\n"
"MIME-Version: 1.0\n"
@@ -24,33 +24,33 @@ msgstr ""
"X-Poedit-SourceCharset: utf-8\n"
msgid "Could not establish connection to sound server"
-msgstr "Ni mogoče vzpostaviti povezave z zvočnim strežnikom"
+msgstr "Povezave z zvočnim strežnikom ni mogoče vzpostaviti"
msgid "Failed to query sound server capabilities"
-msgstr "Napaka med poizvedbo o zmogljivosti zvočnega strežnika"
+msgstr "Poizvedba o zmogljivosti zvočnega strežnika je spodletela"
#. TRANSLATORS: 'song title' by 'artist name'
#, c-format
msgid "'%s' by '%s'"
-msgstr "'%s' izvajalca '%s'"
+msgstr "'%s' - '%s'"
msgid "Internal data stream error."
msgstr "Notranja napaka pretoka podatkov."
msgid "Failed to decode JPEG image"
-msgstr "Napaka med dekodiranjem JPEG slike"
+msgstr "Odkodiranje slike JPEG je spodletelo"
msgid "Could not connect to server"
-msgstr "Ni se mogoče povezati s strežnikom"
+msgstr "S strežnikom se ni mogoče povezati"
msgid "Server does not support seeking."
msgstr "Strežnik ne podpira iskanja."
msgid "Could not resolve server name."
-msgstr "Ni mogoče razrešiti imena strežnika."
+msgstr "Imena strežnika ni mogoče razrešiti."
msgid "Could not establish connection to server."
-msgstr "Ni mogoče vzpostaviti povezave s strežnikom."
+msgstr "Povezave s strežnikom ni mogoče vzpostaviti"
msgid "Secure connection setup failed."
msgstr "Nastavitev varne povezave je spodletela."
@@ -58,7 +58,7 @@ msgstr "Nastavitev varne povezave je spodletela."
msgid ""
"A network error occured, or the server closed the connection unexpectedly."
msgstr ""
-"Prišlo je do omrežne napake ali pa je povezava nepričakovano prekinjena."
+"Prišlo je do omrežne napake ali pa se je povezava nepričakovano prekinila."
msgid "Server sent bad data."
msgstr "Strežnik je poslal slabe podatke."
@@ -67,19 +67,19 @@ msgid "No URL set."
msgstr "Ni nastavljenega naslova URL."
msgid "No or invalid input audio, AVI stream will be corrupt."
-msgstr "Napaka vhodnega zvoka, AVI pretok bo pokvarjen."
+msgstr "Napaka vhodnega zvoka, pretok AVI bo pokvarjen."
msgid "This file contains no playable streams."
msgstr "Datoteka ne vsebuje pretokov za predvajanje."
msgid "This file is invalid and cannot be played."
-msgstr "Datoteka je napačna, zato je ni mogoče predvajati."
+msgstr "Datoteka je neveljavna, zato je ni mogoče predvajati."
msgid "This file is corrupt and cannot be played."
msgstr "Datoteka je pokvarjena, zato je ni mogoče predvajati."
msgid "Invalid atom size."
-msgstr "Neveljavna velikost atoma"
+msgstr "Neveljavna velikost atoma."
msgid "This file is incomplete and cannot be played."
msgstr "Datoteka ni popolna, zato je ni mogoče predvajati."
@@ -96,25 +96,24 @@ msgid ""
"extension plugin for Real media streams."
msgstr ""
"Ni mogoče najti podprtega pretoka. Najverjetneje je treba namestiti vstavek "
-"GStreamer RTSP razširitve za RealMedia pretoke."
+"GStreamer RTSP za pretoke RealMedia."
msgid ""
"No supported stream was found. You might need to allow more transport "
"protocols or may otherwise be missing the right GStreamer RTSP extension "
"plugin."
msgstr ""
-"Ni mogoče najti podprtega pretoka. Najverjetneje je treba omogočiti več "
-"protokolov prenosa, oziroma manjka ustrezen vstavek GStreamer RTSP "
-"razširitve."
+"Podprtega pretoka ni mogoče najti. Najverjetneje je treba omogočiti več "
+"protokolov prenosa ali pa manjka ustrezen vstavek GStreamer RTSP."
msgid "Internal data flow error."
-msgstr "Notranja napaka pretoka podatkov."
+msgstr "Notranja napaka pretočnosti podatkov."
msgid "Volume"
msgstr "Glasnost"
msgid "Bass"
-msgstr "Basovski toni"
+msgstr "Bas"
msgid "Treble"
msgstr "Visoki toni"
@@ -153,22 +152,22 @@ msgid "Out-gain"
msgstr "Izhodna ojačitev"
msgid "Line-1"
-msgstr "Analogni vhod-1"
+msgstr "Analogni vhod 1"
msgid "Line-2"
-msgstr "Analogni vhod-2"
+msgstr "Analogni vhod 2"
msgid "Line-3"
-msgstr "Analogni vhod-3"
+msgstr "Analogni vhod 3"
msgid "Digital-1"
-msgstr "Digitalni vhod-1"
+msgstr "Digitalni vhod 1"
msgid "Digital-2"
-msgstr "Digitalni vhod-2"
+msgstr "Digitalni vhod 2"
msgid "Digital-3"
-msgstr "Digitalni vhod-3"
+msgstr "Digitalni vhod 3"
msgid "Phone-in"
msgstr "Telefonski vhod"
@@ -189,38 +188,38 @@ msgid ""
"Could not open audio device for playback. Device is being used by another "
"application."
msgstr ""
-"Ni mogoče odpreti zvočne naprave za predvajanje. Napravo uporablja drug "
+"Zvočne naprave ni mogoče odpreti za predvajanje. Napravo uporablja drug "
"program."
msgid ""
"Could not open audio device for playback. You don't have permission to open "
"the device."
msgstr ""
-"Ni mogoče odpreti zvočne naprave za predvajanje. Ni ustreznih dovoljenj za "
+"Zvočne naprave ni mogoče odpreti za predvajanje. Nimate dovoljenj za "
"odpiranje naprave."
msgid "Could not open audio device for playback."
-msgstr "Ni mogoče odpreti zvočne naprave za predvajanje."
+msgstr "Zvočne naprave ni mogoče odpreti za predvajanje."
msgid ""
"Could not open audio device for recording. You don't have permission to open "
"the device."
msgstr ""
-"Ni mogoče odpreti zvočne naprave za snemanje. Ni ustreznih dovoljenj za "
-"odpiranje naprave."
+"Zvočne naprave ni mogoče odpreti za snemanje. Nimate dovoljenj za odpiranje "
+"naprave."
msgid "Could not open audio device for recording."
-msgstr "Ni mogoče odpreti zvočne naprave za snemanje."
+msgstr "Zvočne naprave ni mogoče odpreti za snemanje."
msgid "Could not open audio device for mixer control handling."
-msgstr "Ni mogoče odpreti zvočne naprave za mešalni nadzor."
+msgstr "Zvočne naprave ni mogoče odpreti za nadzor mešalnika."
msgid ""
"Could not open audio device for mixer control handling. This version of the "
"Open Sound System is not supported by this element."
msgstr ""
-"Ni mogoče odpreti zvočne naprave za mešalni nadzor. Open Sound System ni "
-"podprt."
+"Zvočne naprave ni mogoče odpreti za nadzor mešalnika. Predmet ne podpira "
+"trenutne različice sistema Open Sound System."
msgid "Master"
msgstr "Glavni"
@@ -241,22 +240,22 @@ msgid "LFE"
msgstr "LFE"
msgid "Surround"
-msgstr "Surround sistem zvoka"
+msgstr "Prostorski"
msgid "Side"
msgstr "Stranski"
msgid "Built-in Speaker"
-msgstr "Vgrajeni zvočnik"
+msgstr "Vgrajen zvočnik"
msgid "AUX 1 Out"
-msgstr "AUX 1 izhod"
+msgstr "Izhod AUX 1"
msgid "AUX 2 Out"
-msgstr "AUX 2 izhod"
+msgstr "Izhod AUX 2"
msgid "AUX Out"
-msgstr "AUX izhod"
+msgstr "Izhod AUX"
msgid "3D Depth"
msgstr "3D globina"
@@ -265,7 +264,7 @@ msgid "3D Center"
msgstr "3D sredina"
msgid "3D Enhance"
-msgstr "3D nadgradnja"
+msgstr "3D izboljšava"
msgid "Telephone"
msgstr "Telefon"
@@ -283,19 +282,19 @@ msgid "Video In"
msgstr "Video vhod"
msgid "AUX 1 In"
-msgstr "AUX 1 vhod"
+msgstr "Vhod AUX 1"
msgid "AUX 2 In"
-msgstr "AUX 2 vhod"
+msgstr "Vhod AUX 2"
msgid "AUX In"
-msgstr "AUX vhod"
+msgstr "Vhod AUX"
msgid "Record Gain"
msgstr "Ojačitev snemanja"
msgid "Output Gain"
-msgstr "Ojačitev odvoda"
+msgstr "Ojačitev izhoda"
msgid "Microphone Boost"
msgstr "Ojačitev mikrofona"
@@ -307,7 +306,7 @@ msgid "Diagnostic"
msgstr "Diagnostika"
msgid "Bass Boost"
-msgstr "Polni basi"
+msgstr "Ojačitev basov"
msgid "Playback Ports"
msgstr "Vrata predvajanja"
@@ -316,10 +315,10 @@ msgid "Input"
msgstr "Vhod"
msgid "Record Source"
-msgstr "Vir zajemanja"
+msgstr "Snemaj vir"
msgid "Monitor Source"
-msgstr "Vir zaslona"
+msgstr "Nadzoruj vir"
msgid "Keyboard Beep"
msgstr "Pisk tipkovnice"
@@ -331,7 +330,7 @@ msgid "Stereo"
msgstr "Stereo"
msgid "Surround Sound"
-msgstr "Surround zvok"
+msgstr "Prostorski zvok"
msgid "Microphone Gain"
msgstr "Ojačitev mikrofona"
@@ -343,7 +342,7 @@ msgid "Microphone Source"
msgstr "Vir mikrofona"
msgid "Jack"
-msgstr "Vhod"
+msgstr "Priključek"
msgid "Center / LFE"
msgstr "Srednji / LFE"
@@ -355,10 +354,10 @@ msgid "Mono Mix"
msgstr "Mono mešanje"
msgid "Input Mix"
-msgstr "Vhodno mešanje"
+msgstr "Mešanje vhoda"
msgid "SPDIF In"
-msgstr "SPDIF vhod"
+msgstr "Vhod SPDIF"
msgid "SPDIF Out"
msgstr "Izhod SPDIF"
@@ -391,10 +390,10 @@ msgid "None"
msgstr "Brez"
msgid "On"
-msgstr "Vklopljeno"
+msgstr "Vključeno"
msgid "Off"
-msgstr "Izklopljeno"
+msgstr "Izključeno"
msgid "Mute"
msgstr "Nemo"
@@ -439,101 +438,102 @@ msgid "Front Panel Line Out"
msgstr "Analogni izhod spredaj"
msgid "Green Connector"
-msgstr "Zeleni spojnik"
+msgstr "Zeleni priključek"
msgid "Pink Connector"
-msgstr "Roza spojnik"
+msgstr "Roza priključek"
msgid "Blue Connector"
-msgstr "Modri spojnik"
+msgstr "Modri priključek"
msgid "White Connector"
-msgstr "Beli spojnik"
+msgstr "Beli priključek"
msgid "Black Connector"
-msgstr "Črni spojnik"
+msgstr "Črni priključek"
msgid "Gray Connector"
-msgstr "Sivi spojnik"
+msgstr "Sivi priključek"
msgid "Orange Connector"
-msgstr "Oranžni spojnik"
+msgstr "Oranžni priključek"
msgid "Red Connector"
-msgstr "Rdeči spojnik"
+msgstr "Rdeči priključek"
msgid "Yellow Connector"
-msgstr "Rumeni spojnik"
+msgstr "Rumeni priključek"
msgid "Green Front Panel Connector"
-msgstr "Zeleni spojnik spredaj"
+msgstr "Zeleni priključek spredaj"
msgid "Pink Front Panel Connector"
-msgstr "Roza spojnik spredaj"
+msgstr "Roza priključek spredaj"
msgid "Blue Front Panel Connector"
-msgstr "Modri spojnik spredaj"
+msgstr "Modri priključek spredaj"
msgid "White Front Panel Connector"
-msgstr "Beli spojnik spredaj"
+msgstr "Beli priključek spredaj"
msgid "Black Front Panel Connector"
-msgstr "Črni spojnik spredaj"
+msgstr "Črni priključek spredaj"
msgid "Gray Front Panel Connector"
-msgstr "Sivi spojnik spredaj"
+msgstr "Sivi priključek spredaj"
msgid "Orange Front Panel Connector"
-msgstr "Oranžni spojnik spredaj"
+msgstr "Oranžni priključek spredaj"
msgid "Red Front Panel Connector"
-msgstr "Rdeči spojnik spredaj"
+msgstr "Rdeči priključek spredaj"
msgid "Yellow Front Panel Connector"
-msgstr "Rumeni spojnik spredaj"
+msgstr "Rumeni priključek spredaj"
msgid "Spread Output"
-msgstr "Razpršeni odvod"
+msgstr "Razširi izhod"
msgid "Downmix"
msgstr "Zmanjševanje kanalov"
msgid "Virtual Mixer Input"
-msgstr "Navidezni mešalni vhod"
+msgstr "Vhod navideznega mešalnika"
msgid "Virtual Mixer Output"
-msgstr "Navidezni mešalni izhod"
+msgstr "Izhod navideznega mešalnika"
msgid "Virtual Mixer Channels"
-msgstr "Navidezni mešalni kanali"
+msgstr "Kanali navideznega mešalnika"
#. TRANSLATORS: name + number of a volume mixer control
#, c-format
msgid "%s %d Function"
-msgstr "%s %d funkcija"
+msgstr "Funkcija %s %d"
#. TRANSLATORS: name of a volume mixer control
#, c-format
msgid "%s Function"
-msgstr "%s funkcija"
+msgstr "Funkcija %s"
msgid ""
"Could not open audio device for playback. This version of the Open Sound "
"System is not supported by this element."
msgstr ""
-"Ni mogoče odpreti zvočne naprave za predvajanje. Open Sound System ni podprt."
+"Zvočne naprave ni mogoče odpreti za predvajanje. Predmet ne podpira trenutne "
+"različice sistema Open Sound System."
msgid "Playback is not supported by this audio device."
-msgstr "Predvajane s to zvočno napravo ni podprto."
+msgstr "Ta zvočna naprava ne podpira predvajanja."
msgid "Audio playback error."
-msgstr "Napaka predvajanja zvoka"
+msgstr "Napaka med predvajanjem zvoka."
msgid "Recording is not supported by this audio device."
msgstr "Snemanje s to zvočno napravo ni podprto."
msgid "Error recording from audio device."
-msgstr "Napaka med shranjevanjem preko zvočne naprave"
+msgstr "Napaka med snemanjem z zvočno napravo."
msgid "Gain"
msgstr "Ojačitev"
@@ -548,8 +548,7 @@ msgstr "Napaka med branjem %d bajtov iz naprave '%s'."
#, c-format
msgid "Got unexpected frame size of %u instead of %u."
msgstr ""
-"Nepričakovana vrednost velikosti okvirja. Pridobljena je vrednost %u, "
-"pričakovana pa %u."
+"Nepričakovana vrednost velikosti okvirja (%u). Pričakovana vrednost je %u."
#, c-format
msgid "Error reading %d bytes on device '%s'."
@@ -560,16 +559,16 @@ msgid ""
"Error getting capabilities for device '%s': It isn't a v4l2 driver. Check if "
"it is a v4l1 driver."
msgstr ""
-"Napaka med pridobivanjem zmožnosti naprave '%s': ni pravega gonilnika v4l2. "
-"Preverite namestitev."
+"Napaka med pridobivanjem zmožnosti naprave '%s': ni gonilnik v4l2. "
+"Preverite, če je gonilnik v4l1."
#, c-format
msgid "Failed to query attributes of input %d in device %s"
-msgstr "Napaka med pregledovanjem atributov poizvedbe vhoda %d naprave %s"
+msgstr "Napaka med poizvedovanjem atributov vhoda %d naprave %s"
#, c-format
msgid "Failed to get setting of tuner %d on device '%s'."
-msgstr "Napaka med pridobivanjem nastavitev uglaševalnika %d na napravi '%s'."
+msgstr "Napaka med pridobivanjem nastavitev uglaševalnika %d naprave '%s'."
#, c-format
msgid "Failed to query norm on device '%s'."
@@ -581,7 +580,7 @@ msgstr "Napaka med pridobivanjem atributov nadzora naprave '%s'."
#, c-format
msgid "Cannot identify device '%s'."
-msgstr "Ni mogoče določiti naprave '%s'."
+msgstr "Naprave '%s' ni mogoče določiti."
#, c-format
msgid "This isn't a device '%s'."
@@ -589,7 +588,7 @@ msgstr "To ni naprava '%s'."
#, c-format
msgid "Could not open device '%s' for reading and writing."
-msgstr "Ni mogoče odpreti naprave '%s' za branje in pisanje."
+msgstr "Naprave '%s' ni mogoče odpreti za branje in pisanje."
#, c-format
msgid "Device '%s' is not a capture device."
@@ -601,16 +600,17 @@ msgstr "Naprava '%s' ni izhodna naprava."
#, c-format
msgid "Failed to set norm for device '%s'."
-msgstr "Napaka med nastavljanjem naprave '%s'."
+msgstr "Napaka med nastavljanjem uravnanosti naprave '%s'."
#, c-format
msgid "Failed to get current tuner frequency for device '%s'."
-msgstr "Napaka med pridobivanjem frekvence uglaševalnika naprave '%s'."
+msgstr ""
+"Napaka med pridobivanjem trenutne frekvence uglaševalnika naprave '%s'."
#, c-format
msgid "Failed to set current tuner frequency for device '%s' to %lu Hz."
msgstr ""
-"Napaka med nastavljanjem frekvence uglaševalnika naprave '%s' na %lu Hz.."
+"Napaka med nastavljanjem frekvence uglaševalnika naprave '%s' na %lu Hz."
#, c-format
msgid "Failed to get signal strength for device '%s'."
@@ -618,40 +618,40 @@ msgstr "Napaka med pridobivanjem moči signala za napravo '%s'."
#, c-format
msgid "Failed to get value for control %d on device '%s'."
-msgstr "Napaka med pridobivanjem vrednosti %d na napravi '%s'."
+msgstr "Napaka med pridobivanjem vrednosti za nadzor %d na napravi '%s'."
#, c-format
msgid "Failed to set value %d for control %d on device '%s'."
-msgstr "Napaka med določanjem vrednosti %d za %d na napravi '%s'."
+msgstr "Napaka med nastavljanjem vrednosti %d za nadzor %d na napravi '%s'."
#, c-format
msgid "Failed to get current input on device '%s'. May be it is a radio device"
msgstr ""
-"Napaka med pridobivanjem vhodnega signala naprave '%s'. Morda je radijska "
+"Napaka med pridobivanjem trenutnega vhoda naprave '%s'. Morda je radijska "
"naprava."
#, c-format
msgid "Failed to set input %d on device %s."
-msgstr "Napaka med določanjem vhoda %d naprave %s."
+msgstr "Napaka med nastavljanjem vhoda %d na napravi %s."
#, c-format
msgid ""
"Failed to get current output on device '%s'. May be it is a radio device"
msgstr ""
-"Napaka med pridobivanjem odvodnega signala naprave '%s'. Morda je radijska "
+"Napaka med pridobivanjem trenutnega izhoda naprave '%s'. Morda je radijska "
"naprava."
#, c-format
msgid "Failed to set output %d on device %s."
-msgstr "Napaka med določanjem odvoda %d naprave %s."
+msgstr "Napaka med nastavljanjem izhoda %d na napravi %s."
#, c-format
msgid "Could not enqueue buffers in device '%s'."
-msgstr "Ni mogoče uvrstiti medpomnilnika naprave '%s'."
+msgstr "Medpomnilnika na napravi '%s' ni mogoče uvrstiti."
#, c-format
msgid "Failed trying to get video frames from device '%s'."
-msgstr "Napaka med poskusom pridobivanja videa preko narpave '%s'."
+msgstr "Napaka med poskusom pridobivanja video sličic z naprave '%s'."
#, c-format
msgid "Failed after %d tries. device %s. system error: %s"
@@ -660,26 +660,25 @@ msgstr ""
#, c-format
msgid "Could not get parameters on device '%s'"
-msgstr "Ni mogoče pridobiti parametrov na napravi '%s'."
+msgstr "Parametrov na napravi '%s' ni mogoče pridobiti."
msgid "Video input device did not accept new frame rate setting."
msgstr ""
-"Vhodni video napravi ni mogoče določiti novih nastavitev hitrosti "
-"predvajanja."
+"Vhodni video napravi ni mogoče določiti novih nastavitev hitrosti sličic."
#, c-format
msgid "Could not map buffers from device '%s'"
-msgstr "Ni mogoče preslikati medpomnilnika naprave '%s'"
+msgstr "Medpomnilnika naprave '%s' ni mogoče preslikati"
#, c-format
msgid "The driver of device '%s' does not support any known capture method."
-msgstr "Gonilnik naprave '%s' ne podpira nobenega znanega načina."
+msgstr "Gonilnik naprave '%s' ne podpira nobenega znanega načina zajemanja."
msgid "Changing resolution at runtime is not yet supported."
msgstr "Spreminjanje ločljivosti med delovanjem še ni podprto."
msgid "Cannot operate without a clock"
-msgstr "Izvajanje opravil brez ure ni mogoče"
+msgstr "Delovanje brez ure ni mogoče"
#~ msgid "Describes the selected input element."
#~ msgstr "Opisuje izbran vnosni predmet."
diff --git a/sys/directsound/gstdirectsoundsink.c b/sys/directsound/gstdirectsoundsink.c
index 462c41210..4eef182fe 100644
--- a/sys/directsound/gstdirectsoundsink.c
+++ b/sys/directsound/gstdirectsoundsink.c
@@ -468,6 +468,7 @@ gst_directsound_sink_prepare (GstAudioSink * asink, GstRingBufferSpec * spec)
spec->segsize += spec->segsize % spec->bytes_per_sample;
spec->segtotal = dsoundsink->buffer_size / spec->segsize;
} else {
+#ifdef WAVE_FORMAT_DOLBY_AC3_SPDIF
wfx.cbSize = 0;
wfx.wFormatTag = WAVE_FORMAT_DOLBY_AC3_SPDIF;
wfx.nChannels = 2;
@@ -478,6 +479,9 @@ gst_directsound_sink_prepare (GstAudioSink * asink, GstRingBufferSpec * spec)
spec->segsize = 6144;
spec->segtotal = 10;
+#else
+ g_assert_not_reached ();
+#endif
}
// Make the final buffer size be an integer number of segments
@@ -738,6 +742,7 @@ gst_directsound_probe_supported_formats (GstDirectSoundSink * dsoundsink,
* Check availability of digital output by trying to create an SPDIF buffer
*/
+#ifdef WAVE_FORMAT_DOLBY_AC3_SPDIF
/* fill the WAVEFORMATEX structure with some standard AC3 over SPDIF params */
memset (&wfx, 0, sizeof (wfx));
wfx.cbSize = 0;
@@ -772,6 +777,9 @@ gst_directsound_probe_supported_formats (GstDirectSoundSink * dsoundsink,
DXGetErrorString9 (hRes));
}
}
+#else
+ caps = gst_caps_subtract (caps, gst_caps_new_simple ("audio/x-iec958", NULL));
+#endif
return caps;
}
diff --git a/sys/oss4/oss4-mixer-slider.c b/sys/oss4/oss4-mixer-slider.c
index cdc910495..e71d1348f 100644
--- a/sys/oss4/oss4-mixer-slider.c
+++ b/sys/oss4/oss4-mixer-slider.c
@@ -228,7 +228,7 @@ gst_oss4_mixer_slider_set_mute (GstOss4MixerSlider * s, gboolean mute)
track->flags &= ~GST_MIXER_TRACK_MUTE;
}
- return FALSE;
+ return ret;
}
GstMixerTrack *
diff --git a/sys/oss4/oss4-mixer-switch.c b/sys/oss4/oss4-mixer-switch.c
index 11d74b46d..0a6ce5b93 100644
--- a/sys/oss4/oss4-mixer-switch.c
+++ b/sys/oss4/oss4-mixer-switch.c
@@ -84,7 +84,6 @@ gboolean
gst_oss4_mixer_switch_get (GstOss4MixerSwitch * s, gboolean * disabled)
{
GstMixerTrack *track;
- int flag;
int enabled = -1;
track = GST_MIXER_TRACK (s);
@@ -95,8 +94,6 @@ gst_oss4_mixer_switch_get (GstOss4MixerSwitch * s, gboolean * disabled)
return FALSE;
}
- flag = (enabled == 0) ? GST_MIXER_TRACK_MUTE : 0;
-
if (enabled) {
track->flags &= ~GST_MIXER_TRACK_MUTE;
} else {
diff --git a/sys/oss4/oss4-property-probe.c b/sys/oss4/oss4-property-probe.c
index 9a625d84f..a99410ea2 100644
--- a/sys/oss4/oss4-property-probe.c
+++ b/sys/oss4/oss4-property-probe.c
@@ -283,7 +283,6 @@ gst_oss4_property_probe_get_values (GstPropertyProbe * probe,
guint prop_id, const GParamSpec * pspec)
{
struct oss_sysinfo si = { {0,}, };
- GstElementClass *klass;
GValueArray *array = NULL;
GstObject *obj;
GList *devices, *l;
@@ -299,7 +298,6 @@ gst_oss4_property_probe_get_values (GstPropertyProbe * probe,
GST_OBJECT_LOCK (obj);
/* figure out whether the element is a source or sink */
- klass = GST_ELEMENT_GET_CLASS (GST_ELEMENT (probe));
if (GST_IS_OSS4_SINK (probe)) {
GST_DEBUG_OBJECT (probe, "probing available output devices");
cap_mask = PCM_CAP_OUTPUT;
diff --git a/sys/oss4/oss4-source.c b/sys/oss4/oss4-source.c
index 0888bd752..9331f8023 100644
--- a/sys/oss4/oss4-source.c
+++ b/sys/oss4/oss4-source.c
@@ -121,15 +121,11 @@ static void
gst_oss4_source_class_init (GstOss4SourceClass * klass)
{
GObjectClass *gobject_class;
- GstElementClass *gstelement_class;
GstBaseSrcClass *gstbasesrc_class;
- GstBaseAudioSrcClass *gstbaseaudiosrc_class;
GstAudioSrcClass *gstaudiosrc_class;
gobject_class = (GObjectClass *) klass;
- gstelement_class = (GstElementClass *) klass;
gstbasesrc_class = (GstBaseSrcClass *) klass;
- gstbaseaudiosrc_class = (GstBaseAudioSrcClass *) klass;
gstaudiosrc_class = (GstAudioSrcClass *) klass;
gobject_class->dispose = gst_oss4_source_dispose;
@@ -928,16 +924,12 @@ static void
gst_oss4_source_mixer_set_mute (GstMixer * mixer, GstMixerTrack * track,
gboolean mute)
{
- GstOss4Source *oss;
-
g_return_if_fail (mixer != NULL);
g_return_if_fail (track != NULL);
g_return_if_fail (GST_IS_MIXER_TRACK (track));
g_return_if_fail (GST_IS_OSS4_SOURCE (mixer));
g_return_if_fail (GST_OSS4_SOURCE_IS_OPEN (mixer));
- oss = GST_OSS4_SOURCE (mixer);
-
/* FIXME: implement gst_oss4_source_mixer_set_mute() - what to do here? */
/* oss4_mixer_set_mute (mixer->mixer, track, mute); */
}
diff --git a/sys/v4l2/gstv4l2radio.c b/sys/v4l2/gstv4l2radio.c
index b1699d381..63a2fed17 100644
--- a/sys/v4l2/gstv4l2radio.c
+++ b/sys/v4l2/gstv4l2radio.c
@@ -384,6 +384,7 @@ gst_v4l2radio_init (GstV4l2Radio * filter, GstV4l2RadioClass * gclass)
gst_v4l2radio_get_input, gst_v4l2radio_set_input, NULL);
filter->v4l2object->frequency = DEFAULT_FREQUENCY;
+ g_free (filter->v4l2object->videodev);
filter->v4l2object->videodev = g_strdup (DEFAULT_PROP_DEVICE);
}
@@ -521,6 +522,7 @@ gst_v4l2radio_set_property (GObject * object, guint prop_id,
gint frequency;
switch (prop_id) {
case ARG_DEVICE:
+ g_free (radio->v4l2object->videodev);
radio->v4l2object->videodev =
g_strdup ((gchar *) g_value_get_string (value));
break;
diff --git a/sys/v4l2/gstv4l2sink.c b/sys/v4l2/gstv4l2sink.c
index aa6785cfe..fcf7e8732 100644
--- a/sys/v4l2/gstv4l2sink.c
+++ b/sys/v4l2/gstv4l2sink.c
@@ -658,7 +658,7 @@ gst_v4l2sink_get_caps (GstBaseSink * bsink)
ret = gst_caps_new_empty ();
- for (walk = v4l2sink->v4l2object->formats; walk; walk = walk->next) {
+ for (walk = formats; walk; walk = walk->next) {
struct v4l2_fmtdesc *format;
GstStructure *template;
diff --git a/sys/v4l2/gstv4l2src.c b/sys/v4l2/gstv4l2src.c
index 4a37d354b..df11dd43f 100644
--- a/sys/v4l2/gstv4l2src.c
+++ b/sys/v4l2/gstv4l2src.c
@@ -578,7 +578,7 @@ gst_v4l2src_get_caps (GstBaseSrc * src)
ret = gst_caps_new_empty ();
- for (walk = v4l2src->v4l2object->formats; walk; walk = walk->next) {
+ for (walk = formats; walk; walk = walk->next) {
struct v4l2_fmtdesc *format;
GstStructure *template;
diff --git a/tests/check/Makefile.am b/tests/check/Makefile.am
index 1ffb7a33f..9fe0e3524 100644
--- a/tests/check/Makefile.am
+++ b/tests/check/Makefile.am
@@ -100,6 +100,9 @@ endif
check_PROGRAMS = \
generic/states \
+ elements/aacparse \
+ elements/ac3parse \
+ elements/amrparse \
$(check_annodex) \
elements/alphacolor \
elements/aspectratiocrop \
@@ -120,6 +123,7 @@ check_PROGRAMS = \
elements/deinterlace \
elements/deinterleave \
elements/equalizer \
+ elements/flacparse \
elements/flvdemux \
elements/flvmux \
elements/icydemux \
@@ -128,7 +132,9 @@ check_PROGRAMS = \
elements/interleave \
elements/level \
elements/matroskamux \
+ elements/mpegaudioparse \
elements/multifile \
+ elements/qtmux \
elements/rganalysis \
elements/rglimiter \
elements/rgvolume \
@@ -144,6 +150,7 @@ check_PROGRAMS = \
elements/y4menc \
pipelines/simple-launch-lines \
pipelines/effectv \
+ pipelines/tagschecking \
pipelines/wavenc \
$(check_flac) \
$(check_gdkpixbuf) \
@@ -177,6 +184,23 @@ VALGRIND_TESTS_DISABLE = \
SUPPRESSIONS = $(top_srcdir)/common/gst.supp $(srcdir)/gst-plugins-good.supp
+# parser unit test convenience lib
+noinst_LTLIBRARIES = libparser.la
+libparser_la_SOURCES = elements/parser.c elements/parser.h
+libparser_la_CFLAGS = \
+ -I$(top_srcdir)/tests/check \
+ $(GST_CHECK_CFLAGS) $(GST_OPTION_CFLAGS)
+
+elements_aacparse_LDADD = libparser.la $(LDADD)
+
+elements_ac3parse_LDADD = libparser.la $(LDADD)
+
+elements_amrparse_LDADD = libparser.la $(LDADD)
+
+elements_flacparse_LDADD = libparser.la $(LDADD)
+
+elements_mpegaudioparse_LDADD = libparser.la $(LDADD)
+
elements_aspectratiocrop_LDADD = $(LDADD)
elements_aspectratiocrop_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(CFLAGS) $(AM_CFLAGS)
@@ -211,11 +235,15 @@ elements_level_LDADD = $(LDADD) $(LIBM)
elements_matroskamux_LDADD = $(GST_BASE_LIBS) $(LDADD) $(LIBM)
+elements_qtmux_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) $(AM_CFLAGS)
+elements_qtmux_LDADD = $(GST_PLUGINS_BASE_LIBS) -lgstpbutils-@GST_MAJORMINOR@ \
+ $(GST_BASE_LIBS) $(GST_LIBS) $(GST_CHECK_LIBS)
+
elements_rtpbin_buffer_list_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) \
$(WARNING_CFLAGS) $(ERROR_CFLAGS) $(GST_CHECK_CFLAGS) $(AM_CFLAGS)
elements_rtpbin_buffer_list_LDADD = $(GST_PLUGINS_BASE_LIBS) \
-lgstnetbuffer-@GST_MAJORMINOR@ -lgstrtp-@GST_MAJORMINOR@ \
- $(GST_BASE_LIBS) $(GST_LIBS_LIBS) $(GST_CHECK_LIBS)
+ $(GST_BASE_LIBS) $(GST_LIBS) $(GST_CHECK_LIBS)
elements_rtpbin_buffer_list_SOURCES = elements/rtpbin_buffer_list.c
elements_souphttpsrc_CFLAGS = $(SOUP_CFLAGS) $(AM_CFLAGS)
diff --git a/tests/check/elements/.gitignore b/tests/check/elements/.gitignore
index 0d06d4576..62c482a18 100644
--- a/tests/check/elements/.gitignore
+++ b/tests/check/elements/.gitignore
@@ -1,5 +1,8 @@
.dirstamp
+aacparse
+ac3parse
alphacolor
+amrparse
apev2mux
aspectratiocrop
audioamplify
@@ -23,6 +26,7 @@ deinterlace
deinterleave
equalizer
gdkpixbufsink
+flacparse
flvdemux
flvmux
icydemux
@@ -33,7 +37,9 @@ interleave
jpegenc
level
matroskamux
+mpegaudioparse
multifile
+qtmux
rganalysis
rglimiter
rgvolume
diff --git a/tests/check/elements/aacparse.c b/tests/check/elements/aacparse.c
new file mode 100644
index 000000000..af10a2779
--- /dev/null
+++ b/tests/check/elements/aacparse.c
@@ -0,0 +1,240 @@
+/*
+ * GStreamer
+ *
+ * unit test for aacparse
+ *
+ * Copyright (C) 2008 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Stefan Kost <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.
+ */
+
+#include <gst/check/gstcheck.h>
+#include "parser.h"
+
+#define SRC_CAPS_CDATA "audio/mpeg, framed=(boolean)false, codec_data=(buffer)1190"
+#define SRC_CAPS_TMPL "audio/mpeg, framed=(boolean)false, mpegversion=(int){2,4}"
+
+#define SINK_CAPS \
+ "audio/mpeg, framed=(boolean)true"
+#define SINK_CAPS_MPEG2 \
+ "audio/mpeg, framed=(boolean)true, mpegversion=2, rate=48000, channels=2"
+#define SINK_CAPS_MPEG4 \
+ "audio/mpeg, framed=(boolean)true, mpegversion=4, rate=96000, channels=2"
+#define SINK_CAPS_TMPL "audio/mpeg, framed=(boolean)true, mpegversion=(int){2,4}"
+
+GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS (SINK_CAPS_TMPL)
+ );
+
+GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS (SRC_CAPS_TMPL)
+ );
+
+/* some data */
+static guint8 adif_header[] = {
+ 'A', 'D', 'I', 'F'
+};
+
+static guint8 adts_frame_mpeg2[] = {
+ 0xff, 0xf9, 0x4c, 0x80, 0x01, 0xff, 0xfc, 0x21, 0x10, 0xd3, 0x20, 0x0c,
+ 0x32, 0x00, 0xc7
+};
+
+static guint8 adts_frame_mpeg4[] = {
+ 0xff, 0xf1, 0x4c, 0x80, 0x01, 0xff, 0xfc, 0x21, 0x10, 0xd3, 0x20, 0x0c,
+ 0x32, 0x00, 0xc7
+};
+
+static guint8 garbage_frame[] = {
+ 0xff, 0xff, 0xff, 0xff, 0xff
+};
+
+/*
+ * Test if the parser pushes data with ADIF header properly and detects the
+ * stream to MPEG4 properly.
+ */
+GST_START_TEST (test_parse_adif_normal)
+{
+ GstParserTest ptest;
+
+ /* ADIF header */
+ gst_parser_test_init (&ptest, adif_header, sizeof (adif_header), 1);
+ /* well, no garbage, followed by random data */
+ ptest.series[2].size = 100;
+ ptest.series[2].num = 3;
+ /* and we do not really expect output frames */
+ ptest.framed = FALSE;
+ /* Check that the negotiated caps are as expected */
+ /* For ADIF parser assumes that data is always version 4 */
+ ptest.sink_caps =
+ gst_caps_from_string (SINK_CAPS_MPEG4 ", stream-format=(string)adif");
+
+ gst_parser_test_run (&ptest, NULL);
+
+ gst_caps_unref (ptest.sink_caps);
+}
+
+GST_END_TEST;
+
+
+GST_START_TEST (test_parse_adts_normal)
+{
+ gst_parser_test_normal (adts_frame_mpeg4, sizeof (adts_frame_mpeg4));
+}
+
+GST_END_TEST;
+
+
+GST_START_TEST (test_parse_adts_drain_single)
+{
+ gst_parser_test_drain_single (adts_frame_mpeg4, sizeof (adts_frame_mpeg4));
+}
+
+GST_END_TEST;
+
+
+GST_START_TEST (test_parse_adts_drain_garbage)
+{
+ gst_parser_test_drain_garbage (adts_frame_mpeg4, sizeof (adts_frame_mpeg4),
+ garbage_frame, sizeof (garbage_frame));
+}
+
+GST_END_TEST;
+
+
+GST_START_TEST (test_parse_adts_split)
+{
+ gst_parser_test_split (adts_frame_mpeg4, sizeof (adts_frame_mpeg4));
+}
+
+GST_END_TEST;
+
+
+GST_START_TEST (test_parse_adts_skip_garbage)
+{
+ gst_parser_test_skip_garbage (adts_frame_mpeg4, sizeof (adts_frame_mpeg4),
+ garbage_frame, sizeof (garbage_frame));
+}
+
+GST_END_TEST;
+
+
+/*
+ * Test if the src caps are set according to stream format (MPEG version).
+ */
+GST_START_TEST (test_parse_adts_detect_mpeg_version)
+{
+ gst_parser_test_output_caps (adts_frame_mpeg2, sizeof (adts_frame_mpeg2),
+ NULL, SINK_CAPS_MPEG2 ", stream-format=(string)adts");
+}
+
+GST_END_TEST;
+
+#define structure_get_int(s,f) \
+ (g_value_get_int(gst_structure_get_value(s,f)))
+#define fail_unless_structure_field_int_equals(s,field,num) \
+ fail_unless_equals_int (structure_get_int(s,field), num)
+/*
+ * Test if the parser handles raw stream and codec_data info properly.
+ */
+GST_START_TEST (test_parse_handle_codec_data)
+{
+ GstCaps *caps;
+ GstStructure *s;
+ const gchar *stream_format;
+
+ /* Push random data. It should get through since the parser should be
+ * initialized because it got codec_data in the caps */
+ caps = gst_parser_test_get_output_caps (NULL, 100, SRC_CAPS_CDATA);
+ fail_unless (caps != NULL);
+
+ /* Check that the negotiated caps are as expected */
+ /* When codec_data is present, parser assumes that data is version 4 */
+ GST_LOG ("aac output caps: %" GST_PTR_FORMAT, caps);
+ s = gst_caps_get_structure (caps, 0);
+ fail_unless (gst_structure_has_name (s, "audio/mpeg"));
+ fail_unless_structure_field_int_equals (s, "mpegversion", 4);
+ fail_unless_structure_field_int_equals (s, "channels", 2);
+ fail_unless_structure_field_int_equals (s, "rate", 48000);
+ fail_unless (gst_structure_has_field (s, "codec_data"));
+ fail_unless (gst_structure_has_field (s, "stream-format"));
+ stream_format = gst_structure_get_string (s, "stream-format");
+ fail_unless (strcmp (stream_format, "raw") == 0);
+
+ gst_caps_unref (caps);
+}
+
+GST_END_TEST;
+
+
+static Suite *
+aacparse_suite (void)
+{
+ Suite *s = suite_create ("aacparse");
+ TCase *tc_chain = tcase_create ("general");
+
+ suite_add_tcase (s, tc_chain);
+ /* ADIF tests */
+ tcase_add_test (tc_chain, test_parse_adif_normal);
+
+ /* ADTS tests */
+ tcase_add_test (tc_chain, test_parse_adts_normal);
+ tcase_add_test (tc_chain, test_parse_adts_drain_single);
+ tcase_add_test (tc_chain, test_parse_adts_drain_garbage);
+ tcase_add_test (tc_chain, test_parse_adts_split);
+ tcase_add_test (tc_chain, test_parse_adts_skip_garbage);
+ tcase_add_test (tc_chain, test_parse_adts_detect_mpeg_version);
+
+ /* Other tests */
+ tcase_add_test (tc_chain, test_parse_handle_codec_data);
+
+ return s;
+}
+
+
+/*
+ * TODO:
+ * - Both push- and pull-modes need to be tested
+ * * Pull-mode & EOS
+ */
+
+int
+main (int argc, char **argv)
+{
+ int nf;
+
+ Suite *s = aacparse_suite ();
+ SRunner *sr = srunner_create (s);
+
+ gst_check_init (&argc, &argv);
+
+ /* init test context */
+ ctx_factory = "aacparse";
+ ctx_sink_template = &sinktemplate;
+ ctx_src_template = &srctemplate;
+
+ srunner_run_all (sr, CK_NORMAL);
+ nf = srunner_ntests_failed (sr);
+ srunner_free (sr);
+
+ return nf;
+}
diff --git a/tests/check/elements/ac3parse.c b/tests/check/elements/ac3parse.c
new file mode 100644
index 000000000..03e8e1dc8
--- /dev/null
+++ b/tests/check/elements/ac3parse.c
@@ -0,0 +1,163 @@
+/*
+ * GStreamer
+ *
+ * unit test for ac3parse
+ *
+ * Copyright (C) 2008 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Stefan Kost <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.
+ */
+
+#include <gst/check/gstcheck.h>
+#include "parser.h"
+
+#define SRC_CAPS_TMPL "audio/x-ac3, framed=(boolean)false"
+#define SINK_CAPS_TMPL "audio/x-ac3, framed=(boolean)true"
+
+GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS (SINK_CAPS_TMPL)
+ );
+
+GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS (SRC_CAPS_TMPL)
+ );
+
+/* some data */
+
+static guint8 ac3_frame[512] = {
+ 0x0b, 0x77, 0xb6, 0xa8, 0x10, 0x40, 0x2f, 0x84,
+ 0x29, 0xcb, 0xfe, 0x75, 0x7c, 0xf9, 0xf3, 0xe7,
+ 0xcf, 0x9f, 0x3e, 0x7c, 0xf9, 0xf3, 0xe7, 0xcf,
+ 0x9f, 0x3e, 0x7c, 0xf9, 0xf3, 0xe7, 0xcf, 0x9f,
+ 0x3e, 0x7c, 0xf9, 0xf3, 0xe7, 0xcf, 0x9f, 0x3e,
+ 0x7c, 0xf9, 0xf3, 0xe7, 0xcf, 0x9f, 0x3e, 0x7c,
+ 0xf9, 0xf3, 0xe7, 0xcf, 0x9f, 0x3e, 0x7c, 0xf9,
+ 0xf3, 0xe7, 0xcf, 0x9f, 0x3e, 0x7c, 0xf9, 0xf3,
+ 0xe7, 0xcf, 0x9f, 0x3e, 0x7c, 0xf9, 0xf3, 0xe7,
+ 0xcf, 0x9f, 0x3e, 0x32, 0xd3, 0xff, 0xc0, 0x06,
+ 0xe9, 0x40, 0x00, 0x6e, 0x94, 0x00, 0x06, 0xe9,
+ 0x40, 0x00, 0x6e, 0x94, 0x00, 0x06, 0xe9, 0x40,
+ 0x00, 0x6e, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+static guint8 garbage_frame[] = {
+ 0xff, 0xff, 0xff, 0xff, 0xff
+};
+
+
+GST_START_TEST (test_parse_normal)
+{
+ gst_parser_test_normal (ac3_frame, sizeof (ac3_frame));
+}
+
+GST_END_TEST;
+
+
+GST_START_TEST (test_parse_drain_single)
+{
+ gst_parser_test_drain_single (ac3_frame, sizeof (ac3_frame));
+}
+
+GST_END_TEST;
+
+
+GST_START_TEST (test_parse_drain_garbage)
+{
+ gst_parser_test_drain_garbage (ac3_frame, sizeof (ac3_frame),
+ garbage_frame, sizeof (garbage_frame));
+}
+
+GST_END_TEST;
+
+
+GST_START_TEST (test_parse_split)
+{
+ gst_parser_test_split (ac3_frame, sizeof (ac3_frame));
+}
+
+GST_END_TEST;
+
+
+GST_START_TEST (test_parse_skip_garbage)
+{
+ gst_parser_test_skip_garbage (ac3_frame, sizeof (ac3_frame),
+ garbage_frame, sizeof (garbage_frame));
+}
+
+GST_END_TEST;
+
+
+GST_START_TEST (test_parse_detect_stream)
+{
+ gst_parser_test_output_caps (ac3_frame, sizeof (ac3_frame),
+ NULL, SINK_CAPS_TMPL ",channels=1,rate=48000");
+}
+
+GST_END_TEST;
+
+
+static Suite *
+ac3parse_suite (void)
+{
+ Suite *s = suite_create ("ac3parse");
+ TCase *tc_chain = tcase_create ("general");
+
+ suite_add_tcase (s, tc_chain);
+ tcase_add_test (tc_chain, test_parse_normal);
+ tcase_add_test (tc_chain, test_parse_drain_single);
+ tcase_add_test (tc_chain, test_parse_drain_garbage);
+ tcase_add_test (tc_chain, test_parse_split);
+ tcase_add_test (tc_chain, test_parse_skip_garbage);
+ tcase_add_test (tc_chain, test_parse_detect_stream);
+
+ return s;
+}
+
+
+/*
+ * TODO:
+ * - Both push- and pull-modes need to be tested
+ * * Pull-mode & EOS
+ */
+
+int
+main (int argc, char **argv)
+{
+ int nf;
+
+ Suite *s = ac3parse_suite ();
+ SRunner *sr = srunner_create (s);
+
+ gst_check_init (&argc, &argv);
+
+ /* init test context */
+ ctx_factory = "ac3parse";
+ ctx_sink_template = &sinktemplate;
+ ctx_src_template = &srctemplate;
+
+ srunner_run_all (sr, CK_NORMAL);
+ nf = srunner_ntests_failed (sr);
+ srunner_free (sr);
+
+ return nf;
+}
diff --git a/tests/check/elements/amrparse.c b/tests/check/elements/amrparse.c
new file mode 100644
index 000000000..e5d64ca57
--- /dev/null
+++ b/tests/check/elements/amrparse.c
@@ -0,0 +1,327 @@
+/*
+ * GStreamer
+ *
+ * unit test for amrparse
+ *
+ * Copyright (C) 2008 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Stefan Kost <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.
+ */
+
+#include <gst/check/gstcheck.h>
+#include "parser.h"
+
+#define SRC_CAPS_NB "audio/x-amr-nb-sh"
+#define SRC_CAPS_WB "audio/x-amr-wb-sh"
+#define SRC_CAPS_ANY "ANY"
+
+#define SINK_CAPS_NB "audio/AMR, rate=8000 , channels=1"
+#define SINK_CAPS_WB "audio/AMR-WB, rate=16000 , channels=1"
+#define SINK_CAPS_ANY "ANY"
+
+#define AMR_FRAME_DURATION (GST_SECOND/50)
+
+static GstStaticPadTemplate sinktemplate_nb = GST_STATIC_PAD_TEMPLATE ("sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS (SINK_CAPS_NB)
+ );
+
+static GstStaticPadTemplate sinktemplate_wb = GST_STATIC_PAD_TEMPLATE ("sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS (SINK_CAPS_WB)
+ );
+
+static GstStaticPadTemplate srctemplate_nb = GST_STATIC_PAD_TEMPLATE ("src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS (SRC_CAPS_NB)
+ );
+
+static GstStaticPadTemplate srctemplate_wb = GST_STATIC_PAD_TEMPLATE ("src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS (SRC_CAPS_WB)
+ );
+
+
+/* some data */
+
+static guint8 frame_data_nb[] = {
+ 0x0c, 0x56, 0x3c, 0x52, 0xe0, 0x61, 0xbc, 0x45,
+ 0x0f, 0x98, 0x2e, 0x01, 0x42, 0x02
+};
+
+static guint8 frame_data_wb[] = {
+ 0x08, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
+ 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
+ 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16
+};
+
+static guint8 frame_hdr_nb[] = {
+ '#', '!', 'A', 'M', 'R', '\n'
+};
+
+static guint8 frame_hdr_wb[] = {
+ '#', '!', 'A', 'M', 'R', '-', 'W', 'B', '\n'
+};
+
+static guint8 garbage_frame[] = {
+ 0xff, 0xff, 0xff, 0xff, 0xff
+};
+
+
+GST_START_TEST (test_parse_nb_normal)
+{
+ gst_parser_test_normal (frame_data_nb, sizeof (frame_data_nb));
+}
+
+GST_END_TEST;
+
+
+GST_START_TEST (test_parse_nb_drain_single)
+{
+ gst_parser_test_drain_single (frame_data_nb, sizeof (frame_data_nb));
+}
+
+GST_END_TEST;
+
+
+GST_START_TEST (test_parse_nb_drain_garbage)
+{
+ gst_parser_test_drain_garbage (frame_data_nb, sizeof (frame_data_nb),
+ garbage_frame, sizeof (garbage_frame));
+}
+
+GST_END_TEST;
+
+
+GST_START_TEST (test_parse_nb_split)
+{
+ gst_parser_test_split (frame_data_nb, sizeof (frame_data_nb));
+}
+
+GST_END_TEST;
+
+
+GST_START_TEST (test_parse_nb_skip_garbage)
+{
+ gst_parser_test_skip_garbage (frame_data_nb, sizeof (frame_data_nb),
+ garbage_frame, sizeof (garbage_frame));
+}
+
+GST_END_TEST;
+
+
+GST_START_TEST (test_parse_nb_detect_stream)
+{
+ GstParserTest ptest;
+ GstCaps *old_ctx_caps;
+
+ /* no input caps, override ctx */
+ old_ctx_caps = ctx_input_caps;
+ ctx_input_caps = NULL;
+
+ /* AMR-NB header */
+ gst_parser_test_init (&ptest, frame_hdr_nb, sizeof (frame_hdr_nb), 1);
+ /* well, no garbage, followed by real data */
+ ptest.series[2].data = frame_data_nb;
+ ptest.series[2].size = sizeof (frame_data_nb);
+ ptest.series[2].num = 10;
+ /* header gets dropped, so ... */
+ /* buffer count will not match */
+ ptest.framed = FALSE;
+ /* total size a bit less */
+ ptest.dropped = sizeof (frame_hdr_nb);
+
+ /* Check that the negotiated caps are as expected */
+ ptest.sink_caps = gst_caps_from_string (SINK_CAPS_NB);
+
+ gst_parser_test_run (&ptest, NULL);
+
+ gst_caps_unref (ptest.sink_caps);
+
+ ctx_input_caps = old_ctx_caps;
+}
+
+GST_END_TEST;
+
+
+GST_START_TEST (test_parse_wb_normal)
+{
+ gst_parser_test_normal (frame_data_wb, sizeof (frame_data_wb));
+}
+
+GST_END_TEST;
+
+
+GST_START_TEST (test_parse_wb_drain_single)
+{
+ gst_parser_test_drain_single (frame_data_wb, sizeof (frame_data_wb));
+}
+
+GST_END_TEST;
+
+
+GST_START_TEST (test_parse_wb_drain_garbage)
+{
+ gst_parser_test_drain_garbage (frame_data_wb, sizeof (frame_data_wb),
+ garbage_frame, sizeof (garbage_frame));
+}
+
+GST_END_TEST;
+
+
+GST_START_TEST (test_parse_wb_split)
+{
+ gst_parser_test_split (frame_data_wb, sizeof (frame_data_wb));
+}
+
+GST_END_TEST;
+
+
+GST_START_TEST (test_parse_wb_skip_garbage)
+{
+ gst_parser_test_skip_garbage (frame_data_wb, sizeof (frame_data_wb),
+ garbage_frame, sizeof (garbage_frame));
+}
+
+GST_END_TEST;
+
+
+GST_START_TEST (test_parse_wb_detect_stream)
+{
+ GstParserTest ptest;
+ GstCaps *old_ctx_caps;
+
+ /* no input caps, override ctx */
+ old_ctx_caps = ctx_input_caps;
+ ctx_input_caps = NULL;
+
+ /* AMR-WB header */
+ gst_parser_test_init (&ptest, frame_hdr_wb, sizeof (frame_hdr_wb), 1);
+ /* well, no garbage, followed by real data */
+ ptest.series[2].data = frame_data_wb;
+ ptest.series[2].size = sizeof (frame_data_wb);
+ ptest.series[2].num = 10;
+ /* header gets dropped, so ... */
+ /* buffer count will not match */
+ ptest.framed = FALSE;
+ /* total size a bit less */
+ ptest.dropped = sizeof (frame_hdr_wb);
+
+ /* Check that the negotiated caps are as expected */
+ ptest.sink_caps = gst_caps_from_string (SINK_CAPS_WB);
+
+ gst_parser_test_run (&ptest, NULL);
+
+ gst_caps_unref (ptest.sink_caps);
+
+ ctx_input_caps = old_ctx_caps;
+}
+
+GST_END_TEST;
+
+
+
+/*
+ * Create test suite.
+ */
+static Suite *
+amrnb_parse_suite (void)
+{
+ Suite *s = suite_create ("amrwb_parse");
+ TCase *tc_chain = tcase_create ("general");
+
+ suite_add_tcase (s, tc_chain);
+ /* AMR-NB tests */
+ tcase_add_test (tc_chain, test_parse_nb_normal);
+ tcase_add_test (tc_chain, test_parse_nb_drain_single);
+ tcase_add_test (tc_chain, test_parse_nb_drain_garbage);
+ tcase_add_test (tc_chain, test_parse_nb_split);
+ tcase_add_test (tc_chain, test_parse_nb_detect_stream);
+ tcase_add_test (tc_chain, test_parse_nb_skip_garbage);
+
+ return s;
+}
+
+static Suite *
+amrwb_parse_suite (void)
+{
+ Suite *s = suite_create ("amrnb_parse");
+ TCase *tc_chain = tcase_create ("general");
+
+ suite_add_tcase (s, tc_chain);
+ /* AMR-WB tests */
+ tcase_add_test (tc_chain, test_parse_wb_normal);
+ tcase_add_test (tc_chain, test_parse_wb_drain_single);
+ tcase_add_test (tc_chain, test_parse_wb_drain_garbage);
+ tcase_add_test (tc_chain, test_parse_wb_split);
+ tcase_add_test (tc_chain, test_parse_wb_detect_stream);
+ tcase_add_test (tc_chain, test_parse_wb_skip_garbage);
+
+ return s;
+}
+
+/*
+ * TODO:
+ * - Both push- and pull-modes need to be tested
+ * * Pull-mode & EOS
+ */
+
+int
+main (int argc, char **argv)
+{
+ int nf;
+ GstCaps *caps;
+
+ Suite *s = amrnb_parse_suite ();
+ SRunner *sr = srunner_create (s);
+
+ gst_check_init (&argc, &argv);
+
+ /* init test context */
+ ctx_factory = "amrparse";
+ ctx_sink_template = &sinktemplate_nb;
+ ctx_src_template = &srctemplate_nb;
+ caps = gst_caps_from_string (SRC_CAPS_NB);
+ g_assert (caps);
+ ctx_input_caps = caps;
+
+ srunner_run_all (sr, CK_NORMAL);
+ nf = srunner_ntests_failed (sr);
+ srunner_free (sr);
+ gst_caps_unref (caps);
+
+ s = amrwb_parse_suite ();
+ sr = srunner_create (s);
+
+ ctx_sink_template = &sinktemplate_wb;
+ ctx_src_template = &srctemplate_wb;
+ caps = gst_caps_from_string (SRC_CAPS_WB);
+ g_assert (caps);
+ ctx_input_caps = caps;
+
+ srunner_run_all (sr, CK_NORMAL);
+ nf += srunner_ntests_failed (sr);
+ srunner_free (sr);
+ gst_caps_unref (caps);
+
+ return nf;
+}
diff --git a/tests/check/elements/deinterlace.c b/tests/check/elements/deinterlace.c
index b111c86f7..6aeb3def8 100644
--- a/tests/check/elements/deinterlace.c
+++ b/tests/check/elements/deinterlace.c
@@ -28,7 +28,7 @@
static gboolean
gst_caps_is_interlaced (GstCaps * caps)
{
- GstStructure *structure;
+ GstStructure G_GNUC_UNUSED *structure;
gboolean interlaced = FALSE;
fail_unless (gst_caps_is_fixed (caps));
diff --git a/tests/check/elements/flacparse.c b/tests/check/elements/flacparse.c
new file mode 100644
index 000000000..0c25bc6f5
--- /dev/null
+++ b/tests/check/elements/flacparse.c
@@ -0,0 +1,299 @@
+/*
+ * GStreamer
+ *
+ * unit test for flacparse
+ *
+ * Copyright (C) 2010 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Stefan Kost <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.
+ */
+
+#include <gst/check/gstcheck.h>
+#include "parser.h"
+
+#define SRC_CAPS_TMPL "audio/x-flac, framed=(boolean)false"
+#define SINK_CAPS_TMPL "audio/x-flac, framed=(boolean)true"
+
+GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS (SINK_CAPS_TMPL)
+ );
+
+GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS (SRC_CAPS_TMPL)
+ );
+
+/* some data */
+static guint8 streaminfo_header[] = {
+ 0x7f, 0x46, 0x4c, 0x41, 0x43, 0x01, 0x00, 0x00,
+ 0x02, 0x66, 0x4c, 0x61, 0x43, 0x00, 0x00, 0x00,
+ 0x22, 0x12, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x0a, 0xc4, 0x40, 0xf0, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00
+};
+
+static guint8 comment_header[] = {
+ 0x84, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00
+};
+
+static guint8 flac_frame[] = {
+ 0xff, 0xf8, 0xa9, 0x08, 0x00, 0x50, 0x18, 0x06,
+ 0x6a, 0x0c, 0xce, 0x13, 0x24, 0x19, 0x68, 0x00,
+ 0x46, 0x23, 0x08, 0xca, 0xcb, 0x58, 0x9c, 0x26,
+ 0x92, 0x30, 0xa6, 0x29, 0x8a, 0xca, 0xd1, 0x18,
+ 0xae, 0x26, 0x5c, 0x90, 0x60, 0xbf, 0x11, 0xad,
+ 0x43, 0x02, 0x06, 0x26, 0xbd, 0x35, 0xdd, 0xa3,
+ 0x11, 0xa6, 0x4d, 0x18, 0x8c, 0x9a, 0xe4, 0x62,
+ 0xd9, 0x23, 0x11, 0x8b, 0xcb, 0x56, 0x55, 0x45,
+ 0xc2, 0x18, 0x56, 0xa2, 0xe2, 0xe1, 0x18, 0x99,
+ 0x54, 0x98, 0x46, 0x4d, 0x08, 0x70, 0x9a, 0x64,
+ 0xc4, 0x18, 0x4f, 0x27, 0x64, 0x31, 0x66, 0x27,
+ 0x79, 0x19, 0x3c, 0x8c, 0x8c, 0xa3, 0x44, 0x18,
+ 0x23, 0xd2, 0x6b, 0x8b, 0x64, 0x8c, 0x21, 0x84,
+ 0xd6, 0x23, 0x13, 0x13, 0x2d, 0x44, 0xca, 0x5a,
+ 0x23, 0x09, 0x93, 0x25, 0x18, 0x10, 0x61, 0x38,
+ 0xb4, 0x60, 0x8f, 0x2c, 0x8d, 0x26, 0xb4, 0xc9,
+ 0xd9, 0x19, 0x19, 0x34, 0xd7, 0x31, 0x06, 0x10,
+ 0xc4, 0x30, 0x83, 0x17, 0xe2, 0x0c, 0x2c, 0xc4,
+ 0xc8, 0xc9, 0x3c, 0x5e, 0x93, 0x11, 0x8a, 0x62,
+ 0x64, 0x8c, 0x26, 0x23, 0x22, 0x30, 0x9a, 0x58,
+ 0x86, 0x04, 0x18, 0x4c, 0xab, 0x2b, 0x26, 0x5c,
+ 0x46, 0x88, 0xcb, 0xb1, 0x0d, 0x26, 0xbb, 0x5e,
+ 0x8c, 0xa7, 0x64, 0x31, 0x3d, 0x31, 0x06, 0x26,
+ 0x43, 0x17, 0xa3, 0x08, 0x61, 0x06, 0x17, 0xc4,
+ 0x62, 0xec, 0x4d, 0x4b, 0x2e, 0x2d, 0x4a, 0x94,
+ 0xa4, 0xc2, 0x31, 0x4c, 0x4c, 0x20, 0xc0, 0x83,
+ 0x14, 0x8c, 0x27, 0x8b, 0x31, 0x23, 0x2f, 0x23,
+ 0x11, 0x91, 0x94, 0x65, 0x1a, 0x20, 0xc2, 0x18,
+ 0x86, 0x51, 0x88, 0x62, 0x7c, 0x43, 0x2e, 0xa3,
+ 0x04, 0x18, 0x8c, 0x20, 0xc2, 0xf5, 0xaa, 0x94,
+ 0xc2, 0x31, 0x32, 0xd2, 0xb2, 0xa2, 0x30, 0xba,
+ 0x10, 0xc2, 0xb5, 0x89, 0xa5, 0x18, 0x10, 0x62,
+ 0x9a, 0x10, 0x61, 0x19, 0x72, 0x71, 0x1a, 0xb9,
+ 0x0c, 0x23, 0x46, 0x10, 0x62, 0x78, 0x81, 0x82,
+ 0x3d, 0x75, 0xea, 0x6b, 0x51, 0x8b, 0x61, 0x06,
+ 0x08, 0x62, 0x32, 0x5e, 0x84, 0x18, 0x27, 0x25,
+ 0xc2, 0x6a, 0x4b, 0x51, 0x31, 0x34, 0x5e, 0x29,
+ 0xa1, 0x3c, 0x4d, 0x26, 0x23, 0x10, 0xc2, 0x6b,
+ 0xb1, 0x0d, 0x11, 0xae, 0x46, 0x88, 0x31, 0x35,
+ 0xb1, 0x06, 0x08, 0x79, 0x7e, 0x4f, 0x53, 0x23,
+ 0x29, 0xa4, 0x30, 0x20, 0x30, 0x23, 0x5a, 0xb2,
+ 0xc8, 0x60, 0x9c, 0x93, 0x13, 0x17, 0x92, 0x98,
+ 0x46, 0x13, 0x54, 0x53, 0x08, 0xcb, 0x13, 0xa1,
+ 0x1a, 0x89, 0xe5, 0x46, 0x08, 0x18, 0x10, 0x30,
+ 0x9d, 0x68, 0xc2, 0x1c, 0x46, 0x46, 0xae, 0x62,
+ 0x1a, 0x46, 0x4e, 0x4d, 0x34, 0x8c, 0xbd, 0x26,
+ 0xc0, 0x40, 0x62, 0xc9, 0xa9, 0x31, 0x74, 0xa8,
+ 0x99, 0x52, 0xb0, 0x8c, 0xa9, 0x29, 0x84, 0x61,
+ 0x19, 0x54, 0x43, 0x02, 0x06, 0x04, 0x32, 0xe5,
+ 0x18, 0x21, 0x91, 0x8b, 0xf2, 0xcc, 0x10, 0x30,
+ 0x8e, 0x23, 0xc4, 0x76, 0x43, 0x08, 0x30, 0x83,
+ 0x08, 0x62, 0x6c, 0x4e, 0xe2, 0x35, 0x96, 0xd0,
+ 0x8e, 0x89, 0x97, 0x42, 0x18, 0x91, 0x84, 0x61,
+ 0x3c, 0x26, 0xa5, 0x2c, 0x4e, 0x17, 0x94, 0xb8,
+ 0xb5, 0xa4, 0xcb, 0x88, 0xc9, 0x84, 0x18, 0xb9,
+ 0x84, 0x19, 0x23, 0x2d, 0xa4, 0x64, 0x62, 0x18,
+ 0x86, 0x53, 0x93, 0xcb, 0x30, 0x8f, 0x2f, 0x93,
+ 0x55, 0xc4, 0xd7, 0x08, 0x62, 0xb8, 0x46, 0x84,
+ 0x68, 0xa3, 0x02, 0xaf, 0x33
+};
+
+static guint8 garbage_frame[] = {
+ 0xff, 0xff, 0xff, 0xff, 0xff
+};
+
+
+GST_START_TEST (test_parse_flac_normal)
+{
+ gst_parser_test_normal (flac_frame, sizeof (flac_frame));
+}
+
+GST_END_TEST;
+
+
+GST_START_TEST (test_parse_flac_drain_single)
+{
+ gst_parser_test_drain_single (flac_frame, sizeof (flac_frame));
+}
+
+GST_END_TEST;
+
+
+GST_START_TEST (test_parse_flac_drain_garbage)
+{
+ /* We always output the after frame garbage too because we
+ * have no way of detecting it
+ */
+#if 0
+ gst_parser_test_drain_garbage (flac_frame, sizeof (flac_frame),
+ garbage_frame, sizeof (garbage_frame));
+#endif
+ guint8 frame[sizeof (flac_frame) + sizeof (garbage_frame)];
+
+ memcpy (frame, flac_frame, sizeof (flac_frame));
+ memcpy (frame + sizeof (flac_frame), garbage_frame, sizeof (garbage_frame));
+
+ gst_parser_test_drain_single (frame, sizeof (frame));
+}
+
+GST_END_TEST;
+
+
+GST_START_TEST (test_parse_flac_split)
+{
+ gst_parser_test_split (flac_frame, sizeof (flac_frame));
+}
+
+GST_END_TEST;
+
+
+GST_START_TEST (test_parse_flac_skip_garbage)
+{
+ /* We always include the garbage into the frame because
+ * we have no easy way for finding the real end of the
+ * frame. The decoder will later skip the garbage
+ */
+#if 0
+ gst_parser_test_skip_garbage (flac_frame, sizeof (flac_frame),
+ garbage_frame, sizeof (garbage_frame));
+#endif
+ guint8 frame[sizeof (flac_frame) + sizeof (garbage_frame)];
+
+ memcpy (frame, flac_frame, sizeof (flac_frame));
+ memcpy (frame + sizeof (flac_frame), garbage_frame, sizeof (garbage_frame));
+
+ gst_parser_test_normal (frame, sizeof (frame));
+}
+
+GST_END_TEST;
+
+
+#define structure_get_int(s,f) \
+ (g_value_get_int(gst_structure_get_value(s,f)))
+#define fail_unless_structure_field_int_equals(s,field,num) \
+ fail_unless_equals_int (structure_get_int(s,field), num)
+/*
+ * Test if the parser handles raw stream and codec_data info properly.
+ */
+GST_START_TEST (test_parse_flac_detect_stream)
+{
+ GstCaps *caps;
+ GstStructure *s;
+ const GValue *streamheader;
+ GArray *bufarr;
+ gint i;
+
+ /* Push random data. It should get through since the parser should be
+ * initialized because it got codec_data in the caps */
+ caps = gst_parser_test_get_output_caps (flac_frame, sizeof (flac_frame),
+ SRC_CAPS_TMPL);
+ fail_unless (caps != NULL);
+
+ /* Check that the negotiated caps are as expected */
+ /* When codec_data is present, parser assumes that data is version 4 */
+ GST_LOG ("flac output caps: %" GST_PTR_FORMAT, caps);
+ s = gst_caps_get_structure (caps, 0);
+ fail_unless (gst_structure_has_name (s, "audio/x-flac"));
+ fail_unless_structure_field_int_equals (s, "channels", 1);
+ fail_unless_structure_field_int_equals (s, "rate", 44100);
+ fail_unless (gst_structure_has_field (s, "streamheader"));
+ streamheader = gst_structure_get_value (s, "streamheader");
+ fail_unless (G_VALUE_TYPE (streamheader) == GST_TYPE_ARRAY);
+ bufarr = g_value_peek_pointer (streamheader);
+ fail_unless (bufarr->len == 2);
+ for (i = 0; i < bufarr->len; i++) {
+ GstBuffer *buf;
+ GValue *bufval = &g_array_index (bufarr, GValue, i);
+
+ fail_unless (G_VALUE_TYPE (bufval) == GST_TYPE_BUFFER);
+ buf = g_value_peek_pointer (bufval);
+ if (i == 0) {
+ fail_unless (GST_BUFFER_SIZE (buf) == sizeof (streaminfo_header));
+ fail_unless (memcmp (buf, streaminfo_header, sizeof (streaminfo_header)));
+ } else if (i == 1) {
+ fail_unless (GST_BUFFER_SIZE (buf) == sizeof (comment_header));
+ fail_unless (memcmp (buf, comment_header, sizeof (comment_header)));
+ }
+ }
+
+ gst_caps_unref (caps);
+}
+
+GST_END_TEST;
+
+
+static Suite *
+flacparse_suite (void)
+{
+ Suite *s = suite_create ("flacparse");
+ TCase *tc_chain = tcase_create ("general");
+
+ suite_add_tcase (s, tc_chain);
+ tcase_add_test (tc_chain, test_parse_flac_normal);
+ tcase_add_test (tc_chain, test_parse_flac_drain_single);
+ tcase_add_test (tc_chain, test_parse_flac_drain_garbage);
+ tcase_add_test (tc_chain, test_parse_flac_split);
+ tcase_add_test (tc_chain, test_parse_flac_skip_garbage);
+
+ /* Other tests */
+ tcase_add_test (tc_chain, test_parse_flac_detect_stream);
+
+ return s;
+}
+
+
+/*
+ * TODO:
+ * - Both push- and pull-modes need to be tested
+ * * Pull-mode & EOS
+ */
+
+int
+main (int argc, char **argv)
+{
+ int nf;
+
+ Suite *s = flacparse_suite ();
+ SRunner *sr = srunner_create (s);
+
+ gst_check_init (&argc, &argv);
+
+ /* init test context */
+ ctx_factory = "flacparse";
+ ctx_sink_template = &sinktemplate;
+ ctx_src_template = &srctemplate;
+ ctx_discard = 3;
+ ctx_headers[0].data = streaminfo_header;
+ ctx_headers[0].size = sizeof (streaminfo_header);
+ ctx_headers[1].data = comment_header;
+ ctx_headers[1].size = sizeof (comment_header);
+ /* custom offsets, and ts always repeatedly 0 */
+ ctx_no_metadata = TRUE;
+
+ srunner_run_all (sr, CK_NORMAL);
+ nf = srunner_ntests_failed (sr);
+ srunner_free (sr);
+
+ return nf;
+}
diff --git a/tests/check/elements/mpegaudioparse.c b/tests/check/elements/mpegaudioparse.c
new file mode 100644
index 000000000..69a08640f
--- /dev/null
+++ b/tests/check/elements/mpegaudioparse.c
@@ -0,0 +1,172 @@
+/*
+ * GStreamer
+ *
+ * unit test for aacparse
+ *
+ * Copyright (C) 2008 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Stefan Kost <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.
+ */
+
+#include <gst/check/gstcheck.h>
+#include "parser.h"
+
+#define SRC_CAPS_TMPL "audio/mpeg, parsed=(boolean)false, mpegversion=(int)1"
+#define SINK_CAPS_TMPL "audio/mpeg, parsed=(boolean)true, mpegversion=(int)1"
+
+GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS (SINK_CAPS_TMPL)
+ );
+
+GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS (SRC_CAPS_TMPL)
+ );
+
+const gchar *factory = "aacparse";
+
+/* some data */
+static guint8 mp3_frame[384] = {
+ 0xff, 0xfb, 0x94, 0xc4, 0xff, 0x83, 0xc0, 0x00,
+ 0x01, 0xa4, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
+ 0x34, 0x80, 0x00, 0x00, 0x04, 0x00,
+};
+
+static guint8 garbage_frame[] = {
+ 0xff, 0xff, 0xff, 0xff, 0xff
+};
+
+
+GST_START_TEST (test_parse_normal)
+{
+ gst_parser_test_normal (mp3_frame, sizeof (mp3_frame));
+}
+
+GST_END_TEST;
+
+
+GST_START_TEST (test_parse_drain_single)
+{
+ gst_parser_test_drain_single (mp3_frame, sizeof (mp3_frame));
+}
+
+GST_END_TEST;
+
+
+GST_START_TEST (test_parse_drain_garbage)
+{
+ gst_parser_test_drain_garbage (mp3_frame, sizeof (mp3_frame),
+ garbage_frame, sizeof (garbage_frame));
+}
+
+GST_END_TEST;
+
+
+GST_START_TEST (test_parse_split)
+{
+ gst_parser_test_split (mp3_frame, sizeof (mp3_frame));
+}
+
+GST_END_TEST;
+
+
+GST_START_TEST (test_parse_skip_garbage)
+{
+ gst_parser_test_skip_garbage (mp3_frame, sizeof (mp3_frame),
+ garbage_frame, sizeof (garbage_frame));
+}
+
+GST_END_TEST;
+
+
+#define structure_get_int(s,f) \
+ (g_value_get_int(gst_structure_get_value(s,f)))
+#define fail_unless_structure_field_int_equals(s,field,num) \
+ fail_unless_equals_int (structure_get_int(s,field), num)
+
+GST_START_TEST (test_parse_detect_stream)
+{
+ GstStructure *s;
+ GstCaps *caps;
+
+ caps = gst_parser_test_get_output_caps (mp3_frame, sizeof (mp3_frame), NULL);
+
+ fail_unless (caps != NULL);
+
+ GST_LOG ("mpegaudio output caps: %" GST_PTR_FORMAT, caps);
+ s = gst_caps_get_structure (caps, 0);
+ fail_unless (gst_structure_has_name (s, "audio/mpeg"));
+ fail_unless_structure_field_int_equals (s, "mpegversion", 1);
+ fail_unless_structure_field_int_equals (s, "layer", 3);
+ fail_unless_structure_field_int_equals (s, "channels", 1);
+ fail_unless_structure_field_int_equals (s, "rate", 48000);
+
+ gst_caps_unref (caps);
+}
+
+GST_END_TEST;
+
+
+static Suite *
+mpegaudioparse_suite (void)
+{
+ Suite *s = suite_create ("mpegaudioparse");
+ TCase *tc_chain = tcase_create ("general");
+
+ suite_add_tcase (s, tc_chain);
+ tcase_add_test (tc_chain, test_parse_normal);
+ tcase_add_test (tc_chain, test_parse_drain_single);
+ tcase_add_test (tc_chain, test_parse_drain_garbage);
+ tcase_add_test (tc_chain, test_parse_split);
+ tcase_add_test (tc_chain, test_parse_skip_garbage);
+ tcase_add_test (tc_chain, test_parse_detect_stream);
+
+ return s;
+}
+
+
+/*
+ * TODO:
+ * - Both push- and pull-modes need to be tested
+ * * Pull-mode & EOS
+ */
+
+int
+main (int argc, char **argv)
+{
+ int nf;
+
+ Suite *s = mpegaudioparse_suite ();
+ SRunner *sr = srunner_create (s);
+
+ gst_check_init (&argc, &argv);
+
+ /* init test context */
+ ctx_factory = "mpegaudioparse";
+ ctx_sink_template = &sinktemplate;
+ ctx_src_template = &srctemplate;
+
+ srunner_run_all (sr, CK_NORMAL);
+ nf = srunner_ntests_failed (sr);
+ srunner_free (sr);
+
+ return nf;
+}
diff --git a/tests/check/elements/parser.c b/tests/check/elements/parser.c
new file mode 100644
index 000000000..759688991
--- /dev/null
+++ b/tests/check/elements/parser.c
@@ -0,0 +1,434 @@
+/*
+ * GStreamer
+ *
+ * unit test for (audio) parser
+ *
+ * Copyright (C) 2008 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Stefan Kost <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.
+ */
+
+#include <gst/check/gstcheck.h>
+#include "elements/parser.h"
+
+
+/* context state variables */
+const gchar *ctx_factory;
+GstStaticPadTemplate *ctx_sink_template;
+GstStaticPadTemplate *ctx_src_template;
+GstCaps *ctx_input_caps;
+GstCaps *ctx_output_caps;
+guint ctx_discard = 0;
+datablob ctx_headers[MAX_HEADERS] = { {NULL, 0}, };
+
+gboolean ctx_no_metadata = FALSE;
+
+/* helper variables */
+GList *current_buf = NULL;
+
+GstPad *srcpad, *sinkpad;
+guint dataoffset = 0;
+GstClockTime ts_counter = 0;
+gint64 offset_counter = 0;
+guint buffer_counter = 0;
+
+typedef struct
+{
+ guint discard;
+ guint buffers_before_offset_skip;
+ guint offset_skip_amount;
+ const guint8 *data_to_verify;
+ guint data_to_verify_size;
+ GstCaps *caps;
+ gboolean no_metadata;
+} buffer_verify_data_s;
+
+/* takes a copy of the passed buffer data */
+static GstBuffer *
+buffer_new (const unsigned char *buffer_data, guint size)
+{
+ GstBuffer *buffer;
+
+ buffer = gst_buffer_new_and_alloc (size);
+ if (buffer_data) {
+ memcpy (GST_BUFFER_DATA (buffer), buffer_data, size);
+ } else {
+ guint i;
+ /* Create a recognizable pattern (loop 0x00 -> 0xff) in the data block */
+ for (i = 0; i < size; i++) {
+ GST_BUFFER_DATA (buffer)[i] = i % 0x100;
+ }
+ }
+
+ gst_buffer_set_caps (buffer, GST_PAD_CAPS (srcpad));
+ GST_BUFFER_OFFSET (buffer) = dataoffset;
+ dataoffset += size;
+ return buffer;
+}
+
+/*
+ * Adds buffer sizes together.
+ */
+static void
+buffer_count_size (void *buffer, void *user_data)
+{
+ guint *sum = (guint *) user_data;
+ *sum += GST_BUFFER_SIZE (buffer);
+}
+
+/*
+ * Verify that given buffer contains predefined ADTS frame.
+ */
+static void
+buffer_verify_data (void *buffer, void *user_data)
+{
+ buffer_verify_data_s *vdata;
+
+ if (!user_data) {
+ return;
+ }
+
+ vdata = (buffer_verify_data_s *) user_data;
+
+ GST_DEBUG ("discard: %d", vdata->discard);
+ if (vdata->discard) {
+ buffer_counter++;
+ if (buffer_counter == vdata->discard) {
+ buffer_counter = 0;
+ vdata->discard = 0;
+ }
+ return;
+ }
+
+ fail_unless (GST_BUFFER_SIZE (buffer) == vdata->data_to_verify_size);
+ fail_unless (memcmp (GST_BUFFER_DATA (buffer), vdata->data_to_verify,
+ vdata->data_to_verify_size) == 0);
+
+ if (vdata->buffers_before_offset_skip) {
+ /* This is for skipping the garbage in some test cases */
+ if (buffer_counter == vdata->buffers_before_offset_skip) {
+ offset_counter += vdata->offset_skip_amount;
+ }
+ }
+ if (!vdata->no_metadata) {
+ fail_unless (GST_BUFFER_TIMESTAMP (buffer) == ts_counter);
+ fail_unless (GST_BUFFER_DURATION (buffer) != 0);
+ fail_unless (GST_BUFFER_OFFSET (buffer) == offset_counter);
+ }
+
+ if (vdata->caps) {
+ GST_LOG ("%" GST_PTR_FORMAT " = %" GST_PTR_FORMAT " ?",
+ GST_BUFFER_CAPS (buffer), vdata->caps);
+ fail_unless (gst_caps_is_equal (GST_BUFFER_CAPS (buffer), vdata->caps));
+ }
+
+ ts_counter += GST_BUFFER_DURATION (buffer);
+ offset_counter += GST_BUFFER_SIZE (buffer);
+ buffer_counter++;
+}
+
+static GstElement *
+setup_element (const gchar * factory, GstStaticPadTemplate * sink_template,
+ GstCaps * sink_caps, GstStaticPadTemplate * src_template,
+ GstCaps * src_caps)
+{
+ GstElement *element;
+ GstBus *bus;
+
+ element = gst_check_setup_element (factory);
+ srcpad = gst_check_setup_src_pad (element, src_template, src_caps);
+ sinkpad = gst_check_setup_sink_pad (element, sink_template, sink_caps);
+ gst_pad_set_active (srcpad, TRUE);
+ gst_pad_set_active (sinkpad, TRUE);
+
+ bus = gst_bus_new ();
+ gst_element_set_bus (element, bus);
+
+ fail_unless (gst_element_set_state (element,
+ GST_STATE_PLAYING) != GST_STATE_CHANGE_FAILURE,
+ "could not set to playing");
+
+ ts_counter = offset_counter = buffer_counter = 0;
+ buffers = NULL;
+ return element;
+}
+
+static void
+cleanup_element (GstElement * element)
+{
+ GstBus *bus;
+
+ /* Free parsed buffers */
+ gst_check_drop_buffers ();
+
+ bus = GST_ELEMENT_BUS (element);
+ gst_bus_set_flushing (bus, TRUE);
+ gst_object_unref (bus);
+
+ gst_pad_set_active (srcpad, FALSE);
+ gst_pad_set_active (sinkpad, FALSE);
+ gst_check_teardown_src_pad (element);
+ gst_check_teardown_sink_pad (element);
+ gst_check_teardown_element (element);
+}
+
+/* inits a standard test */
+void
+gst_parser_test_init (GstParserTest * ptest, guint8 * data, guint size,
+ guint num)
+{
+ /* need these */
+ fail_unless (ctx_factory != NULL);
+ fail_unless (ctx_src_template != NULL);
+ fail_unless (ctx_sink_template != NULL);
+
+ /* basics */
+ memset (ptest, 0, sizeof (*ptest));
+ ptest->factory = ctx_factory;
+ ptest->sink_template = ctx_sink_template;
+ ptest->src_template = ctx_src_template;
+ ptest->framed = TRUE;
+ /* could be NULL if not relevant/needed */
+ ptest->src_caps = ctx_input_caps;
+ ptest->sink_caps = ctx_output_caps;
+ memcpy (ptest->headers, ctx_headers, sizeof (ptest->headers));
+ ptest->discard = ctx_discard;
+ /* some data that pleases caller */
+ ptest->series[0].data = data;
+ ptest->series[0].size = size;
+ ptest->series[0].num = num;
+ ptest->series[0].fpb = 1;
+ ptest->series[1].fpb = 1;
+ ptest->series[2].fpb = 1;
+ ptest->no_metadata = ctx_no_metadata;
+}
+
+/*
+ * Test if the parser pushes clean data properly.
+ */
+void
+gst_parser_test_run (GstParserTest * test, GstCaps ** out_caps)
+{
+ buffer_verify_data_s vdata = { 0, 0, 0, NULL, 0, NULL, FALSE };
+ GstElement *element;
+ GstBuffer *buffer = NULL;
+ GstCaps *src_caps;
+ guint i, j, k;
+ guint frames = 0, size = 0;
+
+ element = setup_element (test->factory, test->sink_template, NULL,
+ test->src_template, test->src_caps);
+
+ /* push some setup headers */
+ for (j = 0; j < G_N_ELEMENTS (test->headers) && test->headers[j].data; j++) {
+ buffer = buffer_new (test->headers[j].data, test->headers[j].size);
+ fail_unless_equals_int (gst_pad_push (srcpad, buffer), GST_FLOW_OK);
+ }
+
+ for (j = 0; j < 3; j++) {
+ for (i = 0; i < test->series[j].num; i++) {
+ /* sanity enforcing */
+ for (k = 0; k < MAX (1, test->series[j].fpb); k++) {
+ if (!k)
+ buffer = buffer_new (test->series[j].data, test->series[j].size);
+ else {
+ GstCaps *caps = gst_buffer_get_caps (buffer);
+
+ buffer = gst_buffer_join (buffer,
+ buffer_new (test->series[j].data, test->series[j].size));
+ if (caps) {
+ gst_buffer_set_caps (buffer, caps);
+ gst_caps_unref (caps);
+ }
+ }
+ }
+ fail_unless_equals_int (gst_pad_push (srcpad, buffer), GST_FLOW_OK);
+ if (j == 0)
+ vdata.buffers_before_offset_skip++;
+ else if (j == 1)
+ vdata.offset_skip_amount += test->series[j].size * test->series[j].fpb;
+ if (j != 1) {
+ frames += test->series[j].fpb;
+ size += test->series[j].size * test->series[j].fpb;
+ }
+ }
+ }
+ gst_pad_push_event (srcpad, gst_event_new_eos ());
+
+ if (G_LIKELY (test->framed))
+ fail_unless_equals_int (g_list_length (buffers) - test->discard, frames);
+
+ /* if all frames are identical, do extended test,
+ * otherwise only verify total data size */
+ if (test->series[0].data && (!test->series[2].size ||
+ (test->series[0].size == test->series[2].size && test->series[2].data
+ && !memcmp (test->series[0].data, test->series[2].data,
+ test->series[0].size)))) {
+ vdata.data_to_verify = test->series[0].data;
+ vdata.data_to_verify_size = test->series[0].size;
+ vdata.caps = test->sink_caps;
+ vdata.discard = test->discard;
+ vdata.no_metadata = test->no_metadata;
+ g_list_foreach (buffers, buffer_verify_data, &vdata);
+ } else {
+ guint datasum = 0;
+
+ g_list_foreach (buffers, buffer_count_size, &datasum);
+ size -= test->dropped;
+ fail_unless_equals_int (datasum, size);
+ }
+
+ src_caps = gst_pad_get_negotiated_caps (sinkpad);
+ GST_LOG ("output caps: %" GST_PTR_FORMAT, src_caps);
+
+ if (test->sink_caps) {
+ GST_LOG ("%" GST_PTR_FORMAT " = %" GST_PTR_FORMAT " ?", src_caps,
+ test->sink_caps);
+ fail_unless (gst_caps_is_equal (src_caps, test->sink_caps));
+ }
+
+ if (out_caps)
+ *out_caps = src_caps;
+ else
+ gst_caps_unref (src_caps);
+
+ cleanup_element (element);
+}
+
+/*
+ * Test if the parser pushes clean data properly.
+ */
+void
+gst_parser_test_normal (guint8 * data, guint size)
+{
+ GstParserTest ptest;
+
+ gst_parser_test_init (&ptest, data, size, 10);
+ gst_parser_test_run (&ptest, NULL);
+}
+
+/*
+ * Test if parser drains its buffers properly. Even one single frame
+ * should be drained and pushed forward when EOS occurs. This single frame
+ * case is special, since normally the parser needs more data to be sure
+ * about stream format. But it should still push the frame forward in EOS.
+ */
+void
+gst_parser_test_drain_single (guint8 * data, guint size)
+{
+ GstParserTest ptest;
+
+ gst_parser_test_init (&ptest, data, size, 1);
+ gst_parser_test_run (&ptest, NULL);
+}
+
+/*
+ * Make sure that parser does not drain garbage when EOS occurs.
+ */
+void
+gst_parser_test_drain_garbage (guint8 * data, guint size, guint8 * garbage,
+ guint gsize)
+{
+ GstParserTest ptest;
+
+ gst_parser_test_init (&ptest, data, size, 1);
+ ptest.series[1].data = garbage;
+ ptest.series[1].size = gsize;
+ ptest.series[1].num = 1;
+ gst_parser_test_run (&ptest, NULL);
+}
+
+/*
+ * Test if parser splits a buffer that contains two frames into two
+ * separate buffers properly.
+ */
+void
+gst_parser_test_split (guint8 * data, guint size)
+{
+ GstParserTest ptest;
+
+ gst_parser_test_init (&ptest, data, size, 10);
+ ptest.series[0].fpb = 2;
+ gst_parser_test_run (&ptest, NULL);
+}
+
+/*
+ * Test if the parser skips garbage between frames properly.
+ */
+void
+gst_parser_test_skip_garbage (guint8 * data, guint size, guint8 * garbage,
+ guint gsize)
+{
+ GstParserTest ptest;
+
+ gst_parser_test_init (&ptest, data, size, 10);
+ ptest.series[1].data = garbage;
+ ptest.series[1].size = gsize;
+ ptest.series[1].num = 1;
+ ptest.series[2].data = data;
+ ptest.series[2].size = size;
+ ptest.series[2].num = 10;
+ gst_parser_test_run (&ptest, NULL);
+}
+
+/*
+ * Test if the src caps are set according to stream format.
+ */
+void
+gst_parser_test_output_caps (guint8 * data, guint size,
+ const gchar * input_caps, const gchar * output_caps)
+{
+ GstParserTest ptest;
+
+ gst_parser_test_init (&ptest, data, size, 10);
+ if (input_caps) {
+ ptest.src_caps = gst_caps_from_string (input_caps);
+ fail_unless (ptest.src_caps != NULL);
+ }
+ if (output_caps) {
+ ptest.sink_caps = gst_caps_from_string (output_caps);
+ fail_unless (ptest.sink_caps != NULL);
+ }
+ gst_parser_test_run (&ptest, NULL);
+ if (ptest.sink_caps)
+ gst_caps_unref (ptest.sink_caps);
+ if (ptest.src_caps)
+ gst_caps_unref (ptest.src_caps);
+}
+
+/*
+ * Test if the src caps are set according to stream format.
+ */
+GstCaps *
+gst_parser_test_get_output_caps (guint8 * data, guint size,
+ const gchar * input_caps)
+{
+ GstParserTest ptest;
+ GstCaps *out_caps;
+
+ gst_parser_test_init (&ptest, data, size, 10);
+ if (input_caps) {
+ ptest.src_caps = gst_caps_from_string (input_caps);
+ fail_unless (ptest.src_caps != NULL);
+ }
+ gst_parser_test_run (&ptest, &out_caps);
+ if (ptest.src_caps)
+ gst_caps_unref (ptest.src_caps);
+
+ return out_caps;
+}
diff --git a/tests/check/elements/parser.h b/tests/check/elements/parser.h
new file mode 100644
index 000000000..470f59421
--- /dev/null
+++ b/tests/check/elements/parser.h
@@ -0,0 +1,95 @@
+/*
+ * GStreamer
+ *
+ * unit test for (audio) parser
+ *
+ * Copyright (C) 2008 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Stefan Kost <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.
+ */
+
+#include <gst/check/gstcheck.h>
+
+#define MAX_HEADERS 10
+
+typedef struct {
+ guint8 *data;
+ guint size;
+} datablob;
+
+/* context state variables; to be set by test using this helper */
+/* mandatory */
+extern const gchar *ctx_factory;
+extern GstStaticPadTemplate *ctx_sink_template;
+extern GstStaticPadTemplate *ctx_src_template;
+/* optional */
+extern GstCaps *ctx_input_caps;
+extern GstCaps *ctx_output_caps;
+extern guint ctx_discard;
+extern datablob ctx_headers[MAX_HEADERS];
+extern gboolean ctx_no_metadata;
+
+/* no refs taken/kept, all up to caller */
+typedef struct
+{
+ const gchar *factory;
+ GstStaticPadTemplate *sink_template;
+ GstStaticPadTemplate *src_template;
+ /* caps that go into element */
+ GstCaps *src_caps;
+ /* optional: output caps to verify */
+ GstCaps *sink_caps;
+ /* initial headers */
+ datablob headers[MAX_HEADERS];
+ /* initial (header) output to forego checking */
+ guint discard;
+ /* series of buffers; middle series considered garbage */
+ struct {
+ /* data and size */
+ guint8 *data;
+ guint size;
+ /* num of frames with above data per buffer */
+ guint fpb;
+ /* num of buffers */
+ guint num;
+ } series[3];
+ /* sigh, weird cases */
+ gboolean framed;
+ guint dropped;
+ gboolean no_metadata;
+} GstParserTest;
+
+void gst_parser_test_init (GstParserTest * ptest, guint8 * data, guint size, guint num);
+
+void gst_parser_test_run (GstParserTest * test, GstCaps ** out_caps);
+
+void gst_parser_test_normal (guint8 *data, guint size);
+
+void gst_parser_test_drain_single (guint8 *data, guint size);
+
+void gst_parser_test_drain_garbage (guint8 *data, guint size, guint8 *garbage, guint gsize);
+
+void gst_parser_test_split (guint8 *data, guint size);
+
+void gst_parser_test_skip_garbage (guint8 *data, guint size, guint8 *garbage, guint gsize);
+
+void gst_parser_test_output_caps (guint8 *data, guint size, const gchar * input_caps,
+ const gchar * output_caps);
+
+GstCaps *gst_parser_test_get_output_caps (guint8 *data, guint size, const gchar * input_caps);
+
diff --git a/tests/check/elements/qtmux.c b/tests/check/elements/qtmux.c
new file mode 100644
index 000000000..a70e34564
--- /dev/null
+++ b/tests/check/elements/qtmux.c
@@ -0,0 +1,590 @@
+/* GStreamer
+ *
+ * unit test for qtmux
+ *
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <gst/check/gstcheck.h>
+#include <gst/pbutils/encoding-profile.h>
+
+/* 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 AUDIO_CAPS_STRING "audio/mpeg, " \
+ "mpegversion = (int) 1, " \
+ "layer = (int) 3, " \
+ "channels = (int) 2, " \
+ "rate = (int) 48000"
+#define VIDEO_CAPS_STRING "video/mpeg, " \
+ "mpegversion = (int) 4, " \
+ "width = (int) 384, " \
+ "height = (int) 288, " \
+ "framerate = (fraction) 25/1"
+
+static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS ("video/quicktime"));
+static GstStaticPadTemplate srcvideotemplate = GST_STATIC_PAD_TEMPLATE ("src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS (VIDEO_CAPS_STRING));
+
+static GstStaticPadTemplate srcaudiotemplate = GST_STATIC_PAD_TEMPLATE ("src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS (AUDIO_CAPS_STRING));
+
+
+/* setup and teardown needs some special handling for muxer */
+static GstPad *
+setup_src_pad (GstElement * element,
+ GstStaticPadTemplate * template, GstCaps * caps, const gchar * sinkname)
+{
+ GstPad *srcpad, *sinkpad;
+
+ GST_DEBUG_OBJECT (element, "setting up sending pad");
+ /* sending pad */
+ srcpad = gst_pad_new_from_static_template (template, "src");
+ fail_if (srcpad == NULL, "Could not create a srcpad");
+ ASSERT_OBJECT_REFCOUNT (srcpad, "srcpad", 1);
+
+ if (!(sinkpad = gst_element_get_static_pad (element, sinkname)))
+ sinkpad = gst_element_get_request_pad (element, sinkname);
+ fail_if (sinkpad == NULL, "Could not get sink pad from %s",
+ GST_ELEMENT_NAME (element));
+ /* references are owned by: 1) us, 2) qtmux, 3) collect pads */
+ ASSERT_OBJECT_REFCOUNT (sinkpad, "sinkpad", 3);
+ if (caps)
+ fail_unless (gst_pad_set_caps (srcpad, caps));
+ 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 */
+
+ /* references are owned by: 1) qtmux, 2) collect pads */
+ ASSERT_OBJECT_REFCOUNT (sinkpad, "sinkpad", 2);
+
+ return srcpad;
+}
+
+static void
+teardown_src_pad (GstPad * srcpad)
+{
+ GstPad *sinkpad;
+
+ /* clean up floating src pad */
+ sinkpad = gst_pad_get_peer (srcpad);
+ fail_if (sinkpad == NULL);
+ /* pad refs held by 1) qtmux 2) collectpads and 3) us (through _get_peer) */
+ ASSERT_OBJECT_REFCOUNT (sinkpad, "sinkpad", 3);
+
+ gst_pad_unlink (srcpad, sinkpad);
+
+ /* after unlinking, pad refs still held by
+ * 1) qtmux and 2) collectpads and 3) us (through _get_peer) */
+ ASSERT_OBJECT_REFCOUNT (sinkpad, "sinkpad", 3);
+ gst_object_unref (sinkpad);
+ /* one more ref is held by element itself */
+
+ /* pad refs held by creator */
+ ASSERT_OBJECT_REFCOUNT (srcpad, "srcpad", 1);
+ gst_object_unref (srcpad);
+}
+
+static GstElement *
+setup_qtmux (GstStaticPadTemplate * srctemplate, const gchar * sinkname)
+{
+ GstElement *qtmux;
+
+ GST_DEBUG ("setup_qtmux");
+ qtmux = gst_check_setup_element ("qtmux");
+ mysrcpad = setup_src_pad (qtmux, srctemplate, NULL, sinkname);
+ mysinkpad = gst_check_setup_sink_pad (qtmux, &sinktemplate, NULL);
+ gst_pad_set_active (mysrcpad, TRUE);
+ gst_pad_set_active (mysinkpad, TRUE);
+
+ return qtmux;
+}
+
+static void
+cleanup_qtmux (GstElement * qtmux, const gchar * sinkname)
+{
+ GST_DEBUG ("cleanup_qtmux");
+ gst_element_set_state (qtmux, GST_STATE_NULL);
+
+ gst_pad_set_active (mysrcpad, FALSE);
+ gst_pad_set_active (mysinkpad, FALSE);
+ teardown_src_pad (mysrcpad);
+ gst_check_teardown_sink_pad (qtmux);
+ gst_check_teardown_element (qtmux);
+}
+
+static void
+check_qtmux_pad (GstStaticPadTemplate * srctemplate, const gchar * sinkname,
+ guint32 dts_method)
+{
+ GstElement *qtmux;
+ GstBuffer *inbuffer, *outbuffer;
+ GstCaps *caps;
+ int num_buffers;
+ int i;
+ guint8 data0[12] = "\000\000\000\024ftypqt ";
+ guint8 data1[8] = "\000\000\000\001mdat";
+ guint8 data2[4] = "moov";
+
+ qtmux = setup_qtmux (srctemplate, sinkname);
+ g_object_set (qtmux, "dts-method", dts_method, NULL);
+ fail_unless (gst_element_set_state (qtmux,
+ GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
+ "could not set to playing");
+
+ inbuffer = gst_buffer_new_and_alloc (1);
+ caps = gst_caps_copy (gst_pad_get_pad_template_caps (mysrcpad));
+ gst_buffer_set_caps (inbuffer, caps);
+ gst_caps_unref (caps);
+ GST_BUFFER_TIMESTAMP (inbuffer) = 0;
+ GST_BUFFER_DURATION (inbuffer) = 40 * GST_MSECOND;
+ ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
+ fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
+
+ /* send eos to have moov written */
+ fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_eos ()) == TRUE);
+
+ num_buffers = g_list_length (buffers);
+ /* at least expect ftyp, mdat header, buffer chunk and moov */
+ fail_unless (num_buffers >= 4);
+
+ for (i = 0; i < num_buffers; ++i) {
+ outbuffer = GST_BUFFER (buffers->data);
+ fail_if (outbuffer == NULL);
+ buffers = g_list_remove (buffers, outbuffer);
+
+ switch (i) {
+ case 0:
+ {
+ /* ftyp header */
+ guint8 *data = GST_BUFFER_DATA (outbuffer);
+
+ fail_unless (GST_BUFFER_SIZE (outbuffer) >= 20);
+ fail_unless (memcmp (data, data0, sizeof (data0)) == 0);
+ fail_unless (memcmp (data + 16, data0 + 8, 4) == 0);
+ break;
+ }
+ case 1: /* mdat header */
+ fail_unless (GST_BUFFER_SIZE (outbuffer) == 16);
+ fail_unless (memcmp (GST_BUFFER_DATA (outbuffer), data1, sizeof (data1))
+ == 0);
+ break;
+ case 2: /* buffer we put in */
+ fail_unless (GST_BUFFER_SIZE (outbuffer) == 1);
+ break;
+ case 3: /* moov */
+ fail_unless (GST_BUFFER_SIZE (outbuffer) > 8);
+ fail_unless (memcmp (GST_BUFFER_DATA (outbuffer) + 4, data2,
+ sizeof (data2)) == 0);
+ break;
+ default:
+ break;
+ }
+
+ ASSERT_BUFFER_REFCOUNT (outbuffer, "outbuffer", 1);
+ gst_buffer_unref (outbuffer);
+ outbuffer = NULL;
+ }
+
+ g_list_free (buffers);
+ buffers = NULL;
+
+ cleanup_qtmux (qtmux, sinkname);
+}
+
+static void
+check_qtmux_pad_fragmented (GstStaticPadTemplate * srctemplate,
+ const gchar * sinkname, guint32 dts_method, gboolean streamable)
+{
+ GstElement *qtmux;
+ GstBuffer *inbuffer, *outbuffer;
+ GstCaps *caps;
+ int num_buffers;
+ int i;
+ guint8 data0[12] = "\000\000\000\024ftypqt ";
+ guint8 data1[4] = "mdat";
+ guint8 data2[4] = "moov";
+ guint8 data3[4] = "moof";
+ guint8 data4[4] = "mfra";
+
+ qtmux = setup_qtmux (srctemplate, sinkname);
+ g_object_set (qtmux, "dts-method", dts_method, NULL);
+ g_object_set (qtmux, "fragment-duration", 2000, NULL);
+ g_object_set (qtmux, "streamable", streamable, NULL);
+ fail_unless (gst_element_set_state (qtmux,
+ GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
+ "could not set to playing");
+
+ inbuffer = gst_buffer_new_and_alloc (1);
+ caps = gst_caps_copy (gst_pad_get_pad_template_caps (mysrcpad));
+ gst_buffer_set_caps (inbuffer, caps);
+ gst_caps_unref (caps);
+ GST_BUFFER_TIMESTAMP (inbuffer) = 0;
+ GST_BUFFER_DURATION (inbuffer) = 40 * GST_MSECOND;
+ ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
+ fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
+
+ /* send eos to have all written */
+ fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_eos ()) == TRUE);
+
+ num_buffers = g_list_length (buffers);
+ /* at least expect ftyp, moov, moof, mdat header, buffer chunk
+ * and optionally mfra */
+ fail_unless (num_buffers >= 5);
+
+ for (i = 0; i < num_buffers; ++i) {
+ outbuffer = GST_BUFFER (buffers->data);
+ fail_if (outbuffer == NULL);
+ buffers = g_list_remove (buffers, outbuffer);
+
+ switch (i) {
+ case 0:
+ {
+ /* ftyp header */
+ guint8 *data = GST_BUFFER_DATA (outbuffer);
+
+ fail_unless (GST_BUFFER_SIZE (outbuffer) >= 20);
+ fail_unless (memcmp (data, data0, sizeof (data0)) == 0);
+ fail_unless (memcmp (data + 16, data0 + 8, 4) == 0);
+ break;
+ }
+ case 1: /* moov */
+ fail_unless (GST_BUFFER_SIZE (outbuffer) > 8);
+ fail_unless (memcmp (GST_BUFFER_DATA (outbuffer) + 4, data2,
+ sizeof (data2)) == 0);
+ break;
+ case 2: /* moof */
+ fail_unless (GST_BUFFER_SIZE (outbuffer) > 8);
+ fail_unless (memcmp (GST_BUFFER_DATA (outbuffer) + 4, data3,
+ sizeof (data3)) == 0);
+ break;
+ case 3: /* mdat header */
+ fail_unless (GST_BUFFER_SIZE (outbuffer) == 8);
+ fail_unless (memcmp (GST_BUFFER_DATA (outbuffer) + 4, data1,
+ sizeof (data1)) == 0);
+ break;
+ case 4: /* buffer we put in */
+ fail_unless (GST_BUFFER_SIZE (outbuffer) == 1);
+ break;
+ case 5: /* mfra */
+ fail_unless (GST_BUFFER_SIZE (outbuffer) > 8);
+ fail_unless (memcmp (GST_BUFFER_DATA (outbuffer) + 4, data4,
+ sizeof (data4)) == 0);
+ break;
+ default:
+ break;
+ }
+
+ ASSERT_BUFFER_REFCOUNT (outbuffer, "outbuffer", 1);
+ gst_buffer_unref (outbuffer);
+ outbuffer = NULL;
+ }
+
+ g_list_free (buffers);
+ buffers = NULL;
+
+ cleanup_qtmux (qtmux, sinkname);
+}
+
+/* dts-method dd */
+
+GST_START_TEST (test_video_pad_dd)
+{
+ check_qtmux_pad (&srcvideotemplate, "video_%d", 0);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_audio_pad_dd)
+{
+ check_qtmux_pad (&srcaudiotemplate, "audio_%d", 0);
+}
+
+GST_END_TEST;
+
+
+GST_START_TEST (test_video_pad_frag_dd)
+{
+ check_qtmux_pad_fragmented (&srcvideotemplate, "video_%d", 0, FALSE);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_audio_pad_frag_dd)
+{
+ check_qtmux_pad_fragmented (&srcaudiotemplate, "audio_%d", 0, FALSE);
+}
+
+GST_END_TEST;
+
+
+GST_START_TEST (test_video_pad_frag_dd_streamable)
+{
+ check_qtmux_pad_fragmented (&srcvideotemplate, "video_%d", 0, TRUE);
+}
+
+GST_END_TEST;
+
+
+GST_START_TEST (test_audio_pad_frag_dd_streamable)
+{
+ check_qtmux_pad_fragmented (&srcaudiotemplate, "audio_%d", 0, TRUE);
+}
+
+GST_END_TEST;
+
+/* dts-method reorder */
+
+GST_START_TEST (test_video_pad_reorder)
+{
+ check_qtmux_pad (&srcvideotemplate, "video_%d", 1);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_audio_pad_reorder)
+{
+ check_qtmux_pad (&srcaudiotemplate, "audio_%d", 1);
+}
+
+GST_END_TEST;
+
+
+GST_START_TEST (test_video_pad_frag_reorder)
+{
+ check_qtmux_pad_fragmented (&srcvideotemplate, "video_%d", 1, FALSE);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_audio_pad_frag_reorder)
+{
+ check_qtmux_pad_fragmented (&srcaudiotemplate, "audio_%d", 1, FALSE);
+}
+
+GST_END_TEST;
+
+
+GST_START_TEST (test_video_pad_frag_reorder_streamable)
+{
+ check_qtmux_pad_fragmented (&srcvideotemplate, "video_%d", 1, TRUE);
+}
+
+GST_END_TEST;
+
+
+GST_START_TEST (test_audio_pad_frag_reorder_streamable)
+{
+ check_qtmux_pad_fragmented (&srcaudiotemplate, "audio_%d", 1, TRUE);
+}
+
+GST_END_TEST;
+
+/* dts-method asc */
+
+GST_START_TEST (test_video_pad_asc)
+{
+ check_qtmux_pad (&srcvideotemplate, "video_%d", 2);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_audio_pad_asc)
+{
+ check_qtmux_pad (&srcaudiotemplate, "audio_%d", 2);
+}
+
+GST_END_TEST;
+
+
+GST_START_TEST (test_video_pad_frag_asc)
+{
+ check_qtmux_pad_fragmented (&srcvideotemplate, "video_%d", 2, FALSE);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_audio_pad_frag_asc)
+{
+ check_qtmux_pad_fragmented (&srcaudiotemplate, "audio_%d", 2, FALSE);
+}
+
+GST_END_TEST;
+
+
+GST_START_TEST (test_video_pad_frag_asc_streamable)
+{
+ check_qtmux_pad_fragmented (&srcvideotemplate, "video_%d", 2, TRUE);
+}
+
+GST_END_TEST;
+
+
+GST_START_TEST (test_audio_pad_frag_asc_streamable)
+{
+ check_qtmux_pad_fragmented (&srcaudiotemplate, "audio_%d", 2, TRUE);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_reuse)
+{
+ GstElement *qtmux = setup_qtmux (&srcvideotemplate, "video_%d");
+ GstBuffer *inbuffer;
+ GstCaps *caps;
+
+ gst_element_set_state (qtmux, GST_STATE_PLAYING);
+ gst_element_set_state (qtmux, GST_STATE_NULL);
+ gst_element_set_state (qtmux, GST_STATE_PLAYING);
+ gst_pad_set_active (mysrcpad, TRUE);
+ gst_pad_set_active (mysinkpad, TRUE);
+
+ inbuffer = gst_buffer_new_and_alloc (1);
+ fail_unless (inbuffer != NULL);
+ caps = gst_caps_copy (gst_pad_get_pad_template_caps (mysrcpad));
+ gst_buffer_set_caps (inbuffer, caps);
+ gst_caps_unref (caps);
+ GST_BUFFER_TIMESTAMP (inbuffer) = 0;
+ GST_BUFFER_DURATION (inbuffer) = 40 * GST_MSECOND;
+ ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
+ fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
+
+ /* send eos to have all written */
+ fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_eos ()) == TRUE);
+
+ cleanup_qtmux (qtmux, "video_%d");
+}
+
+GST_END_TEST;
+
+static GstEncodingContainerProfile *
+create_qtmux_profile (const gchar * variant)
+{
+ GstEncodingContainerProfile *cprof;
+ GstCaps *caps;
+
+ if (variant == NULL) {
+ caps = gst_caps_new_simple ("video/quicktime", NULL);
+ } else {
+ caps = gst_caps_new_simple ("video/quicktime",
+ "variant", G_TYPE_STRING, variant, NULL);
+ }
+
+ cprof = gst_encoding_container_profile_new ("Name", "blah", caps, NULL);
+ gst_caps_unref (caps);
+
+ caps = gst_caps_new_simple ("audio/x-raw-int", "width", G_TYPE_INT, 16,
+ "depth", G_TYPE_INT, 16, "endianness", G_TYPE_INT, 4321,
+ "channels", G_TYPE_INT, 2, "rate", G_TYPE_INT, 44100,
+ "signed", G_TYPE_BOOLEAN, TRUE, NULL);
+ gst_encoding_container_profile_add_profile (cprof,
+ GST_ENCODING_PROFILE (gst_encoding_audio_profile_new (caps, NULL, NULL,
+ 1)));
+ gst_caps_unref (caps);
+
+ return cprof;
+}
+
+GST_START_TEST (test_encodebin)
+{
+ GstEncodingContainerProfile *cprof;
+ GstElement *enc;
+ GstPad *pad;
+
+ enc = gst_element_factory_make ("encodebin", NULL);
+ if (enc == NULL)
+ return;
+
+ /* Make sure encodebin finds a muxer for a profile with a variant field .. */
+ cprof = create_qtmux_profile ("apple");
+ g_object_set (enc, "profile", cprof, NULL);
+ gst_encoding_profile_unref (cprof);
+
+ /* should have created a pad after setting the profile */
+ pad = gst_element_get_static_pad (enc, "audio_0");
+ fail_unless (pad != NULL);
+ gst_object_unref (pad);
+ gst_object_unref (enc);
+
+ /* ... and for a profile without a variant field */
+ enc = gst_element_factory_make ("encodebin", NULL);
+ cprof = create_qtmux_profile (NULL);
+ g_object_set (enc, "profile", cprof, NULL);
+ gst_encoding_profile_unref (cprof);
+
+ /* should have created a pad after setting the profile */
+ pad = gst_element_get_static_pad (enc, "audio_0");
+ fail_unless (pad != NULL);
+ gst_object_unref (pad);
+ gst_object_unref (enc);
+}
+
+GST_END_TEST;
+
+static Suite *
+qtmux_suite (void)
+{
+ Suite *s = suite_create ("qtmux");
+ TCase *tc_chain = tcase_create ("general");
+
+ suite_add_tcase (s, tc_chain);
+ tcase_add_test (tc_chain, test_video_pad_dd);
+ tcase_add_test (tc_chain, test_audio_pad_dd);
+ tcase_add_test (tc_chain, test_video_pad_frag_dd);
+ tcase_add_test (tc_chain, test_audio_pad_frag_dd);
+ tcase_add_test (tc_chain, test_video_pad_frag_dd_streamable);
+ tcase_add_test (tc_chain, test_audio_pad_frag_dd_streamable);
+
+ tcase_add_test (tc_chain, test_video_pad_reorder);
+ tcase_add_test (tc_chain, test_audio_pad_reorder);
+ tcase_add_test (tc_chain, test_video_pad_frag_reorder);
+ tcase_add_test (tc_chain, test_audio_pad_frag_reorder);
+ tcase_add_test (tc_chain, test_video_pad_frag_reorder_streamable);
+ tcase_add_test (tc_chain, test_audio_pad_frag_reorder_streamable);
+
+ tcase_add_test (tc_chain, test_video_pad_asc);
+ tcase_add_test (tc_chain, test_audio_pad_asc);
+ tcase_add_test (tc_chain, test_video_pad_frag_asc);
+ tcase_add_test (tc_chain, test_audio_pad_frag_asc);
+ tcase_add_test (tc_chain, test_video_pad_frag_asc_streamable);
+ tcase_add_test (tc_chain, test_audio_pad_frag_asc_streamable);
+
+ tcase_add_test (tc_chain, test_reuse);
+ tcase_add_test (tc_chain, test_encodebin);
+
+ return s;
+}
+
+GST_CHECK_MAIN (qtmux)
diff --git a/tests/check/elements/rtp-payloading.c b/tests/check/elements/rtp-payloading.c
index 245f33219..b2160f4a5 100644
--- a/tests/check/elements/rtp-payloading.c
+++ b/tests/check/elements/rtp-payloading.c
@@ -291,13 +291,12 @@ rtp_pipeline_run (rtp_pipeline * p)
for (i = 0; i < LOOP_COUNT; i++) {
const char *frame_data_pointer = p->frame_data;
int res;
-
int frame_count = p->frame_count;
/* Write in to the pipe. */
while (frame_count > 0) {
res = write (p->fd[1], frame_data_pointer, p->frame_data_size);
-
+ fail_unless_equals_int (res, p->frame_data_size);
frame_data_pointer += p->frame_data_size;
frame_count--;
}
diff --git a/tests/check/pipelines/.gitignore b/tests/check/pipelines/.gitignore
index e81a5ec56..4396b2fa1 100644
--- a/tests/check/pipelines/.gitignore
+++ b/tests/check/pipelines/.gitignore
@@ -2,6 +2,7 @@
effectv
flacdec
simple-launch-lines
+tagschecking
wavenc
wavpack
*.check.xml
diff --git a/tests/check/pipelines/flacdec.c b/tests/check/pipelines/flacdec.c
index abf9a058c..ce8546e99 100644
--- a/tests/check/pipelines/flacdec.c
+++ b/tests/check/pipelines/flacdec.c
@@ -110,7 +110,6 @@ GST_START_TEST (test_decode_seek_full)
GstEvent *event;
GstBuffer *buffer = NULL;
guint16 first_sample = 0;
- gboolean result;
guint size = 0;
gchar *path =
g_build_filename (GST_TEST_FILES_PATH, "audiotestsrc.flac", NULL);
@@ -133,7 +132,7 @@ GST_START_TEST (test_decode_seek_full)
/* do a seek that should give us the complete output */
event = gst_event_new_seek (1.0, GST_FORMAT_DEFAULT, GST_SEEK_FLAG_FLUSH,
GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_SET, 20480);
- result = gst_element_send_event (appsink, event);
+ fail_unless (gst_element_send_event (appsink, event));
gst_element_set_state (pipeline, GST_STATE_PLAYING);
@@ -169,7 +168,6 @@ GST_START_TEST (test_decode_seek_partial)
GstElement *appsink;
GstEvent *event;
GstBuffer *buffer = NULL;
- gboolean result;
guint size = 0;
guint16 first_sample = 0;
gchar *path =
@@ -194,7 +192,7 @@ GST_START_TEST (test_decode_seek_partial)
event = gst_event_new_seek (1.0, GST_FORMAT_DEFAULT, GST_SEEK_FLAG_FLUSH,
GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_SET, 1024);
GST_DEBUG ("seeking");
- result = gst_element_send_event (appsink, event);
+ fail_unless (gst_element_send_event (appsink, event));
GST_DEBUG ("seeked");
gst_element_set_state (pipeline, GST_STATE_PLAYING);
diff --git a/tests/check/pipelines/tagschecking.c b/tests/check/pipelines/tagschecking.c
new file mode 100644
index 000000000..91a556c52
--- /dev/null
+++ b/tests/check/pipelines/tagschecking.c
@@ -0,0 +1,350 @@
+/* GStreamer
+ * Copyright (C) 2008 Nokia Corporation. (contact <stefan.kost@nokia.com>)
+ * Copyright (C) 2010 Thiago Santos <thiago.sousa.santos@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.
+ */
+
+#include <gst/check/gstcheck.h>
+
+static GstTagList *received_tags = NULL;
+
+static gboolean
+bus_handler (GstBus * bus, GstMessage * message, gpointer data)
+{
+ GMainLoop *loop = (GMainLoop *) data;
+
+ switch (message->type) {
+ case GST_MESSAGE_EOS:
+ g_main_loop_quit (loop);
+ break;
+ case GST_MESSAGE_WARNING:
+ 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);
+ g_error_free (gerror);
+ g_free (debug);
+ g_main_loop_quit (loop);
+ break;
+ }
+ case GST_MESSAGE_TAG:{
+ if (received_tags == NULL) {
+ gst_message_parse_tag (message, &received_tags);
+ } else {
+ GstTagList *tl = NULL, *ntl = NULL;
+
+ gst_message_parse_tag (message, &tl);
+ if (tl) {
+ ntl = gst_tag_list_merge (received_tags, tl, GST_TAG_MERGE_PREPEND);
+ if (ntl) {
+ GST_LOG ("taglists merged: %" GST_PTR_FORMAT, ntl);
+ gst_tag_list_free (received_tags);
+ received_tags = ntl;
+ }
+ gst_tag_list_free (tl);
+ }
+ }
+ break;
+ }
+ default:
+ break;
+ }
+
+ return TRUE;
+}
+
+/*
+ * Creates a pipeline in the form:
+ * fakesrc num-buffers=1 ! caps ! muxer ! filesink location=file
+ *
+ * And sets the tags in tag_str into the muxer via tagsetter.
+ */
+static void
+test_mux_tags (const gchar * tag_str, const gchar * caps,
+ const gchar * muxer, const gchar * file)
+{
+ GstElement *pipeline;
+ GstBus *bus;
+ GMainLoop *loop;
+ GstTagList *sent_tags;
+ GstElement *mux;
+ GstTagSetter *setter;
+ gchar *launch_str;
+
+ GST_DEBUG ("testing xmp muxing on : %s", muxer);
+
+ launch_str = g_strdup_printf ("fakesrc num-buffers=1 ! %s ! %s name=mux ! "
+ "filesink location=%s name=sink", caps, muxer, file);
+ pipeline = gst_parse_launch (launch_str, NULL);
+ g_free (launch_str);
+ fail_unless (pipeline != NULL);
+
+ mux = gst_bin_get_by_name (GST_BIN (pipeline), "mux");
+ fail_unless (mux != NULL);
+
+ loop = g_main_loop_new (NULL, TRUE);
+ fail_unless (loop != NULL);
+
+ bus = gst_element_get_bus (pipeline);
+ fail_unless (bus != NULL);
+ gst_bus_add_watch (bus, bus_handler, loop);
+ gst_object_unref (bus);
+
+ gst_element_set_state (pipeline, GST_STATE_READY);
+
+ setter = GST_TAG_SETTER (mux);
+ fail_unless (setter != NULL);
+ sent_tags = gst_structure_from_string (tag_str, NULL);
+ fail_unless (sent_tags != NULL);
+ gst_tag_setter_merge_tags (setter, sent_tags, GST_TAG_MERGE_REPLACE);
+ gst_tag_list_free (sent_tags);
+
+ gst_element_set_state (pipeline, GST_STATE_PLAYING);
+ g_main_loop_run (loop);
+
+ gst_element_set_state (pipeline, GST_STATE_NULL);
+
+ g_main_loop_unref (loop);
+ g_object_unref (mux);
+ g_object_unref (pipeline);
+}
+
+/*
+ * Makes a pipeline in the form:
+ * filesrc location=file ! demuxer ! fakesink
+ *
+ * And gets the tags that are posted on the bus to compare
+ * with the tags in 'tag_str'
+ */
+static void
+test_demux_tags (const gchar * tag_str, const gchar * demuxer,
+ const gchar * file)
+{
+ GstElement *pipeline;
+ GstBus *bus;
+ GMainLoop *loop;
+ GstTagList *sent_tags;
+ gint i, j, n_recv, n_sent;
+ const gchar *name_sent, *name_recv;
+ const GValue *value_sent, *value_recv;
+ gboolean found;
+ gint comparison;
+ GstElement *demux;
+ gchar *launch_str;
+
+ GST_DEBUG ("testing tags : %s", tag_str);
+
+ if (received_tags) {
+ gst_tag_list_free (received_tags);
+ received_tags = NULL;
+ }
+
+ launch_str = g_strdup_printf ("filesrc location=%s ! %s name=demux ! "
+ "fakesink", file, demuxer);
+ pipeline = gst_parse_launch (launch_str, NULL);
+ g_free (launch_str);
+ fail_unless (pipeline != NULL);
+
+ demux = gst_bin_get_by_name (GST_BIN (pipeline), "demux");
+ fail_unless (demux != NULL);
+
+ loop = g_main_loop_new (NULL, TRUE);
+ fail_unless (loop != NULL);
+
+ bus = gst_element_get_bus (pipeline);
+ fail_unless (bus != NULL);
+ gst_bus_add_watch (bus, bus_handler, loop);
+ gst_object_unref (bus);
+
+ sent_tags = gst_structure_from_string (tag_str, NULL);
+ fail_unless (sent_tags != NULL);
+
+ gst_element_set_state (pipeline, GST_STATE_PLAYING);
+ g_main_loop_run (loop);
+
+ GST_DEBUG ("mainloop done : %p", received_tags);
+
+ /* verify tags */
+ fail_unless (received_tags != NULL);
+ n_recv = gst_structure_n_fields (received_tags);
+ n_sent = gst_structure_n_fields (sent_tags);
+ fail_unless (n_recv >= n_sent);
+ /* FIXME: compare taglits values */
+ for (i = 0; i < n_sent; i++) {
+ name_sent = gst_structure_nth_field_name (sent_tags, i);
+ value_sent = gst_structure_get_value (sent_tags, name_sent);
+ found = FALSE;
+ for (j = 0; j < n_recv; j++) {
+ name_recv = gst_structure_nth_field_name (received_tags, j);
+ if (!strcmp (name_sent, name_recv)) {
+ value_recv = gst_structure_get_value (received_tags, name_recv);
+ comparison = gst_value_compare (value_sent, value_recv);
+ if (comparison != GST_VALUE_EQUAL) {
+ gchar *vs = g_strdup_value_contents (value_sent);
+ gchar *vr = g_strdup_value_contents (value_recv);
+ GST_DEBUG ("sent = %s:'%s', recv = %s:'%s'",
+ G_VALUE_TYPE_NAME (value_sent), vs,
+ G_VALUE_TYPE_NAME (value_recv), vr);
+ g_free (vs);
+ g_free (vr);
+ }
+ fail_unless (comparison == GST_VALUE_EQUAL,
+ "tag item %s has been received with different type or value",
+ name_sent);
+ found = TRUE;
+ break;
+ }
+ }
+ fail_unless (found, "tag item %s is lost", name_sent);
+ }
+
+ gst_tag_list_free (received_tags);
+ received_tags = NULL;
+ gst_tag_list_free (sent_tags);
+
+ gst_element_set_state (pipeline, GST_STATE_NULL);
+
+ g_main_loop_unref (loop);
+ g_object_unref (demux);
+ g_object_unref (pipeline);
+}
+
+/*
+ * Tests if the muxer/demuxer pair can serialize the tags in 'tag_str'
+ * to a file and recover them correctly.
+ *
+ * 'caps' are used to assure the muxer accepts the fake buffer fakesrc
+ * will send to it.
+ */
+static void
+test_tags (const gchar * tag_str, const gchar * caps, const gchar * muxer,
+ const gchar * demuxer)
+{
+ gchar *tmpfile;
+ gchar *tmp;
+
+ tmp = g_strdup_printf ("%s%d", "gst-check-xmp-test-", g_random_int ());
+ tmpfile = g_build_filename (g_get_tmp_dir (), tmp, NULL);
+ g_free (tmp);
+
+ GST_DEBUG ("testing tags : %s", tag_str);
+ test_mux_tags (tag_str, caps, muxer, tmpfile);
+ test_demux_tags (tag_str, demuxer, tmpfile);
+ g_free (tmpfile);
+}
+
+#define H264_CAPS "video/x-h264, width=(int)320, height=(int)240," \
+ " framerate=(fraction)30/1, codec_data=(buffer)" \
+ "01401592ffe10017674d401592540a0fd8088000000300" \
+ "8000001e478b175001000468ee3c80, stream-format=(string)avc"
+
+#define COMMON_TAGS \
+ "taglist,title=test_title," \
+ "artist=test_artist," \
+ "keywords=\"key1,key2\"," \
+ "description=test_desc"
+
+GST_START_TEST (test_common_tags)
+{
+ if (!gst_default_registry_check_feature_version ("qtdemux", 0, 10, 23)) {
+ GST_INFO ("Skipping test, qtdemux either not available or too old");
+ return;
+ }
+ test_tags (COMMON_TAGS, H264_CAPS, "qtmux", "qtdemux");
+ test_tags (COMMON_TAGS, H264_CAPS, "mp4mux", "qtdemux");
+ test_tags (COMMON_TAGS, H264_CAPS, "gppmux", "qtdemux");
+}
+
+GST_END_TEST;
+
+#define GEO_LOCATION_TAGS \
+ "taglist,geo-location-country=Brazil," \
+ "geo-location-city=\"Campina Grande\"," \
+ "geo-location-sublocation=Bodocongo," \
+ "geo-location-latitude=-12.125," \
+ "geo-location-longitude=56.75," \
+ "geo-location-elevation=327.5"
+
+GST_START_TEST (test_geo_location_tags)
+{
+ if (!gst_default_registry_check_feature_version ("qtdemux", 0, 10, 23)) {
+ GST_INFO ("Skipping test, qtdemux either not available or too old");
+ return;
+ }
+ test_tags (GEO_LOCATION_TAGS, H264_CAPS, "qtmux", "qtdemux");
+ test_tags (GEO_LOCATION_TAGS, H264_CAPS, "mp4mux", "qtdemux");
+ test_tags (GEO_LOCATION_TAGS, H264_CAPS, "gppmux", "qtdemux");
+}
+
+GST_END_TEST;
+
+
+#define USER_TAGS \
+ "taglist,user-rating=(uint)85"
+
+GST_START_TEST (test_user_tags)
+{
+ if (!gst_default_registry_check_feature_version ("qtdemux", 0, 10, 23)) {
+ GST_INFO ("Skipping test, qtdemux either not available or too old");
+ return;
+ }
+
+ test_tags (USER_TAGS, H264_CAPS, "qtmux", "qtdemux");
+ test_tags (USER_TAGS, H264_CAPS, "mp4mux", "qtdemux");
+ test_tags (USER_TAGS, H264_CAPS, "gppmux", "qtdemux");
+}
+
+GST_END_TEST;
+
+static Suite *
+metadata_suite (void)
+{
+ Suite *s = suite_create ("tagschecking");
+
+ TCase *tc_chain = tcase_create ("general");
+
+ /* time out after 60s, not the default 3 */
+ tcase_set_timeout (tc_chain, 60);
+
+ suite_add_tcase (s, tc_chain);
+ tcase_add_test (tc_chain, test_common_tags);
+ tcase_add_test (tc_chain, test_geo_location_tags);
+ tcase_add_test (tc_chain, test_user_tags);
+
+ return s;
+}
+
+int
+main (int argc, char **argv)
+{
+ int nf;
+
+ Suite *s = metadata_suite ();
+
+ SRunner *sr = srunner_create (s);
+
+ gst_check_init (&argc, &argv);
+
+ srunner_run_all (sr, CK_NORMAL);
+ nf = srunner_ntests_failed (sr);
+ srunner_free (sr);
+
+ return nf;
+}
diff --git a/tests/examples/cairo/cairo_overlay.c b/tests/examples/cairo/cairo_overlay.c
index c941b53b2..cae4c137c 100644
--- a/tests/examples/cairo/cairo_overlay.c
+++ b/tests/examples/cairo/cairo_overlay.c
@@ -167,4 +167,6 @@ main (int argc, char **argv)
gst_element_set_state (pipeline, GST_STATE_NULL);
gst_object_unref (pipeline);
+
+ return 0;
}
diff --git a/tests/examples/level/level-example.c b/tests/examples/level/level-example.c
index ece364714..a85d751b6 100644
--- a/tests/examples/level/level-example.c
+++ b/tests/examples/level/level-example.c
@@ -82,7 +82,7 @@ main (int argc, char *argv[])
GstElement *pipeline;
GstCaps *caps;
GstBus *bus;
- gint watch_id;
+ guint watch_id;
GMainLoop *loop;
gst_init (&argc, &argv);
@@ -102,9 +102,12 @@ main (int argc, char *argv[])
gst_bin_add_many (GST_BIN (pipeline), audiotestsrc, audioconvert, level,
fakesink, NULL);
- g_assert (gst_element_link (audiotestsrc, audioconvert));
- g_assert (gst_element_link_filtered (audioconvert, level, caps));
- g_assert (gst_element_link (level, fakesink));
+ if (!gst_element_link (audiotestsrc, audioconvert))
+ g_error ("Failed to link audiotestsrc and audioconvert");
+ if (!gst_element_link_filtered (audioconvert, level, caps))
+ g_error ("Failed to link audioconvert and level");
+ if (!gst_element_link (level, fakesink))
+ g_error ("Failed to link level and fakesink");
/* make sure we'll get messages */
g_object_set (G_OBJECT (level), "message", TRUE, NULL);
@@ -120,5 +123,7 @@ main (int argc, char *argv[])
loop = g_main_loop_new (NULL, FALSE);
g_main_loop_run (loop);
+ g_source_remove (watch_id);
+ g_main_loop_unref (loop);
return 0;
}
diff --git a/tests/examples/rtp/server-alsasrc-PCMA.c b/tests/examples/rtp/server-alsasrc-PCMA.c
index c237d7e5b..d61ec30cb 100644
--- a/tests/examples/rtp/server-alsasrc-PCMA.c
+++ b/tests/examples/rtp/server-alsasrc-PCMA.c
@@ -117,8 +117,6 @@ main (int argc, char *argv[])
GstElement *rtpbin, *rtpsink, *rtcpsink, *rtcpsrc;
GstElement *pipeline;
GMainLoop *loop;
- gboolean res;
- GstPadLinkReturn lres;
GstPad *srcpad, *sinkpad;
/* always init first */
@@ -145,9 +143,11 @@ main (int argc, char *argv[])
gst_bin_add_many (GST_BIN (pipeline), audiosrc, audioconv, audiores,
audioenc, audiopay, NULL);
- res = gst_element_link_many (audiosrc, audioconv, audiores, audioenc,
- audiopay, NULL);
- g_assert (res == TRUE);
+ if (!gst_element_link_many (audiosrc, audioconv, audiores, audioenc,
+ audiopay, NULL)) {
+ g_error ("Failed to link audiosrc, audioconv, audioresample, "
+ "audio encoder and audio payloader");
+ }
/* the rtpbin element */
rtpbin = gst_element_factory_make ("gstrtpbin", "rtpbin");
@@ -175,32 +175,32 @@ main (int argc, char *argv[])
/* now link all to the rtpbin, start by getting an RTP sinkpad for session 0 */
sinkpad = gst_element_get_request_pad (rtpbin, "send_rtp_sink_0");
srcpad = gst_element_get_static_pad (audiopay, "src");
- lres = gst_pad_link (srcpad, sinkpad);
- g_assert (lres == GST_PAD_LINK_OK);
+ if (gst_pad_link (srcpad, sinkpad) != GST_PAD_LINK_OK)
+ g_error ("Failed to link audio payloader to rtpbin");
gst_object_unref (srcpad);
/* get the RTP srcpad that was created when we requested the sinkpad above and
* link it to the rtpsink sinkpad*/
srcpad = gst_element_get_static_pad (rtpbin, "send_rtp_src_0");
sinkpad = gst_element_get_static_pad (rtpsink, "sink");
- lres = gst_pad_link (srcpad, sinkpad);
- g_assert (lres == GST_PAD_LINK_OK);
+ if (gst_pad_link (srcpad, sinkpad) != GST_PAD_LINK_OK)
+ g_error ("Failed to link rtpbin to rtpsink");
gst_object_unref (srcpad);
gst_object_unref (sinkpad);
/* get an RTCP srcpad for sending RTCP to the receiver */
srcpad = gst_element_get_request_pad (rtpbin, "send_rtcp_src_0");
sinkpad = gst_element_get_static_pad (rtcpsink, "sink");
- lres = gst_pad_link (srcpad, sinkpad);
- g_assert (lres == GST_PAD_LINK_OK);
+ if (gst_pad_link (srcpad, sinkpad) != GST_PAD_LINK_OK)
+ g_error ("Failed to link rtpbin to rtcpsink");
gst_object_unref (sinkpad);
/* we also want to receive RTCP, request an RTCP sinkpad for session 0 and
* link it to the srcpad of the udpsrc for RTCP */
srcpad = gst_element_get_static_pad (rtcpsrc, "src");
sinkpad = gst_element_get_request_pad (rtpbin, "recv_rtcp_sink_0");
- lres = gst_pad_link (srcpad, sinkpad);
- g_assert (lres == GST_PAD_LINK_OK);
+ if (gst_pad_link (srcpad, sinkpad) != GST_PAD_LINK_OK)
+ g_error ("Failed to link rtcpsrc to rtpbin");
gst_object_unref (srcpad);
/* set the pipeline to playing */
diff --git a/tests/icles/videocrop-test.c b/tests/icles/videocrop-test.c
index 94656342d..a4874e160 100644
--- a/tests/icles/videocrop-test.c
+++ b/tests/icles/videocrop-test.c
@@ -190,7 +190,6 @@ main (int argc, char **argv)
GError *opt_err = NULL;
GstElement *pipeline, *src, *filter1, *crop, *scale, *filter2, *csp, *sink;
- GMainLoop *loop;
GstCaps *filter_caps = NULL;
GList *caps_list, *l;
@@ -209,8 +208,6 @@ main (int argc, char **argv)
GST_DEBUG_CATEGORY_INIT (videocrop_test_debug, "videocroptest", 0, "vctest");
- loop = g_main_loop_new (NULL, FALSE);
-
pipeline = gst_pipeline_new ("pipeline");
src = gst_element_factory_make ("videotestsrc", "videotestsrc");
g_assert (src != NULL);
diff --git a/tests/icles/ximagesrc-test.c b/tests/icles/ximagesrc-test.c
index f51913a99..a01bf656b 100644
--- a/tests/icles/ximagesrc-test.c
+++ b/tests/icles/ximagesrc-test.c
@@ -37,7 +37,6 @@ int
main (int argc, char **argv)
{
GstElement *pipeline;
- GstBus *bus;
#ifndef G_DISABLE_ASSERT
GstState state, pending;
#endif
@@ -53,8 +52,6 @@ main (int argc, char **argv)
loop = g_main_loop_new (NULL, FALSE);
- bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
-
gst_element_set_state (pipeline, GST_STATE_PLAYING);
/* lets check it gets to PLAYING */
diff --git a/win32/common/config.h b/win32/common/config.h
index 84520c479..f332d338e 100644
--- a/win32/common/config.h
+++ b/win32/common/config.h
@@ -43,13 +43,13 @@
#define GST_LICENSE "LGPL"
/* package name in plugins */
-#define GST_PACKAGE_NAME "GStreamer Good Plug-ins git"
+#define GST_PACKAGE_NAME "GStreamer Good Plug-ins prerelease"
/* package origin */
#define GST_PACKAGE_ORIGIN "Unknown package origin"
/* GStreamer package release date/time for plugins as YYYY-MM-DD */
-#define GST_PACKAGE_RELEASE_DATETIME "2011-03-08T16:22Z"
+#define GST_PACKAGE_RELEASE_DATETIME "2011-04-16T15:21Z"
/* struct v4l2_buffer missing */
#undef GST_V4L2_MISSING_BUFDECL
@@ -211,6 +211,12 @@
/* Define to enable Jack (used by jack). */
#undef HAVE_JACK
+/* defined if jack >= 0.120.1 is available */
+#undef HAVE_JACK_0_120_1
+
+/* defined if jack >= 1.9.7 is available */
+#undef HAVE_JACK_1_9_7
+
/* Define to enable jpeg library (used by jpeg). */
#undef HAVE_JPEG
@@ -390,7 +396,7 @@
#define PACKAGE_NAME "GStreamer Good Plug-ins"
/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "GStreamer Good Plug-ins 0.10.28.1"
+#define PACKAGE_STRING "GStreamer Good Plug-ins 0.10.28.2"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "gst-plugins-good"
@@ -399,7 +405,7 @@
#undef PACKAGE_URL
/* Define to the version of this package. */
-#define PACKAGE_VERSION "0.10.28.1"
+#define PACKAGE_VERSION "0.10.28.2"
/* directory where plugins are located */
#ifdef _DEBUG
@@ -430,7 +436,7 @@
#undef STDC_HEADERS
/* Version number of package */
-#define VERSION "0.10.28.1"
+#define VERSION "0.10.28.2"
/* old wavpack API */
#undef WAVPACK_OLD_API
diff --git a/win32/common/gstrtpbin-marshal.c b/win32/common/gstrtpbin-marshal.c
index 5fae29f3f..633995758 100644
--- a/win32/common/gstrtpbin-marshal.c
+++ b/win32/common/gstrtpbin-marshal.c
@@ -322,79 +322,7 @@ gst_rtp_bin_marshal_UINT64__BOOLEAN_UINT64 (GClosure * closure,
g_value_set_uint64 (return_value, v_return);
}
-/* BOOL:POINTER,BOOL (gstrtpbin-marshal.list:10) */
-void
-gst_rtp_bin_marshal_BOOLEAN__POINTER_BOOLEAN (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__POINTER_BOOLEAN) (gpointer data1,
- gpointer arg_1, gboolean arg_2, gpointer data2);
- register GMarshalFunc_BOOLEAN__POINTER_BOOLEAN callback;
- register GCClosure *cc = (GCClosure *) closure;
- register gpointer data1, data2;
- gboolean 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_BOOLEAN__POINTER_BOOLEAN) (marshal_data ? marshal_data :
- cc->callback);
-
- v_return = callback (data1,
- g_marshal_value_peek_pointer (param_values + 1),
- g_marshal_value_peek_boolean (param_values + 2), data2);
-
- g_value_set_boolean (return_value, v_return);
-}
-
-/* VOID:UINT,UINT,UINT,UINT,POINTER (gstrtpbin-marshal.list:11) */
-void
-gst_rtp_bin_marshal_VOID__UINT_UINT_UINT_UINT_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 void (*GMarshalFunc_VOID__UINT_UINT_UINT_UINT_POINTER) (gpointer
- data1, guint arg_1, guint arg_2, guint arg_3, guint arg_4, gpointer arg_5,
- gpointer data2);
- register GMarshalFunc_VOID__UINT_UINT_UINT_UINT_POINTER callback;
- register GCClosure *cc = (GCClosure *) closure;
- register gpointer data1, data2;
-
- g_return_if_fail (n_param_values == 6);
-
- 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__UINT_UINT_UINT_UINT_POINTER) (marshal_data ?
- marshal_data : cc->callback);
-
- callback (data1,
- g_marshal_value_peek_uint (param_values + 1),
- g_marshal_value_peek_uint (param_values + 2),
- g_marshal_value_peek_uint (param_values + 3),
- g_marshal_value_peek_uint (param_values + 4),
- g_marshal_value_peek_pointer (param_values + 5), data2);
-}
-
-/* VOID:UINT64 (gstrtpbin-marshal.list:12) */
+/* VOID:UINT64 (gstrtpbin-marshal.list:10) */
void
gst_rtp_bin_marshal_VOID__UINT64 (GClosure * closure,
GValue * return_value G_GNUC_UNUSED,
diff --git a/win32/common/gstrtpbin-marshal.h b/win32/common/gstrtpbin-marshal.h
index 6d25b4412..d5242046e 100644
--- a/win32/common/gstrtpbin-marshal.h
+++ b/win32/common/gstrtpbin-marshal.h
@@ -74,24 +74,7 @@ extern void gst_rtp_bin_marshal_UINT64__BOOLEAN_UINT64 (GClosure *closure,
gpointer marshal_data);
#define gst_rtp_bin_marshal_UINT64__BOOL_UINT64 gst_rtp_bin_marshal_UINT64__BOOLEAN_UINT64
-/* BOOL:POINTER,BOOL (gstrtpbin-marshal.list:10) */
-extern void gst_rtp_bin_marshal_BOOLEAN__POINTER_BOOLEAN (GClosure *closure,
- GValue *return_value,
- guint n_param_values,
- const GValue *param_values,
- gpointer invocation_hint,
- gpointer marshal_data);
-#define gst_rtp_bin_marshal_BOOL__POINTER_BOOL gst_rtp_bin_marshal_BOOLEAN__POINTER_BOOLEAN
-
-/* VOID:UINT,UINT,UINT,UINT,POINTER (gstrtpbin-marshal.list:11) */
-extern void gst_rtp_bin_marshal_VOID__UINT_UINT_UINT_UINT_POINTER (GClosure *closure,
- GValue *return_value,
- guint n_param_values,
- const GValue *param_values,
- gpointer invocation_hint,
- gpointer marshal_data);
-
-/* VOID:UINT64 (gstrtpbin-marshal.list:12) */
+/* VOID:UINT64 (gstrtpbin-marshal.list:10) */
extern void gst_rtp_bin_marshal_VOID__UINT64 (GClosure *closure,
GValue *return_value,
guint n_param_values,